播放这段代码时:
half x = if even x
then Just (x `div` 2)
else Nothing
printMaybe m = case m of
Nothing -> putStrLn "List was empty!"
Just x -> print x
main = do
let halfN = Just 4 >>= half
halfN >>= printMaybe
发生错误:
main.hs:9:1: error:
* Couldn't match expected type `IO t0' with actual type `Maybe ()'
* In the expression: main
When checking the type of the IO action `main'
|
9 | main = do
| ^
main.hs:11:13: error:
* Couldn't match type `IO' with `Maybe'
Expected type: Maybe a0 -> Maybe ()
Actual type: Maybe a0 -> IO ()
* In the second argument of `(>>=)', namely `printMaybe'
In a stmt of a 'do' block: halfN >>= printMaybe
In the expression:
do let halfN = Just 4 >>= half
halfN >>= printMaybe
|
11 | halfN >>= printMaybe
这是解决此问题的一种方法:
half x = if even x
then Just (x `div` 2)
else Nothing
printMaybe m = case m of
Nothing -> putStrLn "List was empty!"
Just x -> print x
main = do
let halfN = Just 4 >>= half
printMaybe $ halfN
我无法弄清楚为什么原始程序不起作用。首先,我们得到函数中数字的一半half
(以 monad 的形式Maybe
),然后我们将这个值“推”到输出函数 -printMaybe
中。
为什么原始版本的代码不起作用?
>>=
这不是“推”运算符,而是一元绑定并且,从签名中可以看出,它只绑定相同类型的容器
Maybe
withMaybe
,IO
withIO
等。您是否尝试连接和
那些。不同类型的容器 -
Maybe
和IO
, 内容类型不兼容Integral a => a
vs.Show a => Maybe a
.这是使用此功能的正确方法,替代方法(根据单子第一定律等效,但在这种情况下完全不合适)可能是
同样适用于 and
Just 4 >>= half
,最好将其替换为half 4
因为 forMonad Maybe
正确使用示例
还有一件事:不要忘记指定函数签名,这会让你更容易理解你做了什么(或没做什么)