不能 return 可能导致 IO Monad
Can not return maybe result in the IO Monad
我不明白为什么这个代码示例不起作用,但在 RWH 书中它起作用了:
module Monads where
import Data.Maybe
import Control.Monad
amap=[("a",1),("bb",2)]
bmap=[(1,100),(2,200)]
final=[(100,1000),(200,2000)]
f::String->IO (Maybe Int)
f par=do
a<-lookup par amap
b<-lookup a bmap
lookup b final
它不起作用,我不明白它是如何工作的,因为最后一行 returns 是 Maybe something
而不是 IO something
.
我也试过将最后一行更改为:
return (lookup b final)
根据我的推理应该是完美的(查找 returns a Maybe Int
然后用 return
包装它)
我在使用 return
时出现以下错误
* Couldn't match type `Maybe' with `IO'
Expected type: IO Integer
Actual type: Maybe Integer
* In a stmt of a 'do' block: b <- lookup a bmap
In the expression:
do a <- lookup par amap
b <- lookup a bmap
return (lookup b final)
In an equation for `f':
f par
= do a <- lookup par amap
b <- lookup a bmap
return (lookup b final)
|
11 | b<-lookup a bmap
| ^^^^^^^^^^^^^
对于给定的类型签名,您需要将最终调用 lookup
的值 return 提升为 IO
值。
f::String->IO (Maybe Int)
f par = return $ do
a <- lookup par amap
b <- lookup a bmap
lookup b final
do
表达式是使用 >>=
的语法糖,它在 Maybe
monad 中运行,在本例中不是 IO
,而是 return
获取结果 Maybe Int
值并生成所需的 IO (Maybe Int)
值。它可以脱糖为
f par = return (lookup par amap >>= \a -> lookup a bmap >>= \b -> lookup b final)
但是,除了强制您使用 return
的类型签名之外,f
没有其他 要求 到 return 一个 IO
值;它的参数和三个关联列表中的任何一个都不以任何方式涉及 IO
,因此您可以简单地更改类型签名以消除对 IO
的任何引用并纯粹在 Maybe
monad 中操作。
f :: String -> Maybe Int
f par = do
a <- lookup par amap
b <- lookup a bmap
lookup b final
旁白:摆脱 do
由于您将对 lookup
的各种调用链接在一起,如果您能以无点样式将每个结果提供给下一个调用,那就太好了。为此,您需要颠倒 lookup
接受其参数的顺序。使用 flip
很简单:flip lookup :: [(a,b)] -> a -> Maybe b
.
f :: String -> Maybe Int
f par = let lookup' = flip lookup
in lookup' amap par >>= lookup' bmap >>= lookup' final
更进一步,您可以使用从 Control.Monad
导入的 >=>
运算符完全删除对 par
的引用。将其类型与 >>=
:
的类型进行比较
:t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
:t (>=>)
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
不是以 Maybe
值开始,而是 编写 对 lookup'
的调用,并将起始字符串提供给函数。
f :: String -> Maybe Int
f = let lookup' = flip lookup
in lookup' amap >=> lookup' bmap >=> lookup' final
我不明白为什么这个代码示例不起作用,但在 RWH 书中它起作用了:
module Monads where
import Data.Maybe
import Control.Monad
amap=[("a",1),("bb",2)]
bmap=[(1,100),(2,200)]
final=[(100,1000),(200,2000)]
f::String->IO (Maybe Int)
f par=do
a<-lookup par amap
b<-lookup a bmap
lookup b final
它不起作用,我不明白它是如何工作的,因为最后一行 returns 是 Maybe something
而不是 IO something
.
我也试过将最后一行更改为:
return (lookup b final)
根据我的推理应该是完美的(查找 returns a Maybe Int
然后用 return
包装它)
我在使用 return
* Couldn't match type `Maybe' with `IO'
Expected type: IO Integer
Actual type: Maybe Integer
* In a stmt of a 'do' block: b <- lookup a bmap
In the expression:
do a <- lookup par amap
b <- lookup a bmap
return (lookup b final)
In an equation for `f':
f par
= do a <- lookup par amap
b <- lookup a bmap
return (lookup b final)
|
11 | b<-lookup a bmap
| ^^^^^^^^^^^^^
对于给定的类型签名,您需要将最终调用 lookup
的值 return 提升为 IO
值。
f::String->IO (Maybe Int)
f par = return $ do
a <- lookup par amap
b <- lookup a bmap
lookup b final
do
表达式是使用 >>=
的语法糖,它在 Maybe
monad 中运行,在本例中不是 IO
,而是 return
获取结果 Maybe Int
值并生成所需的 IO (Maybe Int)
值。它可以脱糖为
f par = return (lookup par amap >>= \a -> lookup a bmap >>= \b -> lookup b final)
但是,除了强制您使用 return
的类型签名之外,f
没有其他 要求 到 return 一个 IO
值;它的参数和三个关联列表中的任何一个都不以任何方式涉及 IO
,因此您可以简单地更改类型签名以消除对 IO
的任何引用并纯粹在 Maybe
monad 中操作。
f :: String -> Maybe Int
f par = do
a <- lookup par amap
b <- lookup a bmap
lookup b final
旁白:摆脱 do
由于您将对 lookup
的各种调用链接在一起,如果您能以无点样式将每个结果提供给下一个调用,那就太好了。为此,您需要颠倒 lookup
接受其参数的顺序。使用 flip
很简单:flip lookup :: [(a,b)] -> a -> Maybe b
.
f :: String -> Maybe Int
f par = let lookup' = flip lookup
in lookup' amap par >>= lookup' bmap >>= lookup' final
更进一步,您可以使用从 Control.Monad
导入的 >=>
运算符完全删除对 par
的引用。将其类型与 >>=
:
:t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
:t (>=>)
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
不是以 Maybe
值开始,而是 编写 对 lookup'
的调用,并将起始字符串提供给函数。
f :: String -> Maybe Int
f = let lookup' = flip lookup
in lookup' amap >=> lookup' bmap >=> lookup' final