播放这段代码时:
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中。
为什么原始版本的代码不起作用?
>>=这不是“推”运算符,而是一元绑定并且,从签名中可以看出,它只绑定相同类型的容器
MaybewithMaybe,IOwithIO等。您是否尝试连接和
那些。不同类型的容器 -
Maybe和IO, 内容类型不兼容Integral a => avs.Show a => Maybe a.这是使用此功能的正确方法,替代方法(根据单子第一定律等效,但在这种情况下完全不合适)可能是
同样适用于 and
Just 4 >>= half,最好将其替换为half 4因为 forMonad Maybe正确使用示例
还有一件事:不要忘记指定函数签名,这会让你更容易理解你做了什么(或没做什么)