Ger*_*wer 8 monads haskell type-mismatch do-notation
为什么允许使用此功能:
-- function 1
myfunc :: String
myfunc = do
x <- (return True)
show x
Run Code Online (Sandbox Code Playgroud)
这不是:
-- function 2
myfunc :: String
myfunc = do
x <- getLine
show x
Run Code Online (Sandbox Code Playgroud)
编译错误:
Couldn't match type `[]' with `IO'
Expected type: IO Char
Actual type: String
Run Code Online (Sandbox Code Playgroud)
我明白为什么功能 2 不应该工作,但为什么功能 1 工作呢?
为什么这会起作用:
-- function 3
myfunc = do
x <- getLine
return (show x)
Run Code Online (Sandbox Code Playgroud)
我知道它IO String
然后返回,但是为什么函数 1 也没有被迫这样做?
sri*_*sri 12
在function1 中,do
块 inmyfunc
正在列表 monad 中工作,因为String
实际上只是[Char]
. 在那里,return True
只需创建[True]
. 当你这样做时x <- return True
,“提取”True
出来[True]
并将其绑定到x
. 下一行show x
转换True
为 String "True"
。这是编译器值期望看到的返回值,最终工作正常。
同时,在function2 中,do
myfunc 中的块也在列表 monad 上工作(出于同样的原因,String
真的是[Char]
),但调用getLine
仅在IO
monad 中可用。所以不出所料,这失败了。
-- 编辑 1
OP增加了一个功能3
-- function 3
myfunc :: String
myfunc = do
x <- getLine
return (show x)
Run Code Online (Sandbox Code Playgroud)
不,这不应该出于同样的原因function2失败。
-- 编辑 2
OP 已更新 function3以修复复制粘贴错误。
-- function 3
myfunc = do
x <- getLine
return (show x)
Run Code Online (Sandbox Code Playgroud)
评论中提到了这一点,但为了清楚起见,这是有效的,因为当未指定类型信息时,GHC 会做出最佳推断,并且在看到 之后getLine
,它会认为IO String
它确实提供了getLine
.
注意 - 我以尽可能随意的语气写了这个答案,而不会出错,目的是让它平易近人。
do
块在任意Monad
. 的Monad
,在这种情况下,是[]
。Monad
列表的实例基于列表理解:
instance Monad [] where
return x = [x]
xs >>= f = [y | x <- xs, y <- f x]
Run Code Online (Sandbox Code Playgroud)
您可以do
这样对符号进行脱糖:
myfunc :: String
myfunc = do
x <- (return True)
show x
-- ==>
myfunc = [y | x <- return True, y <- show x]
-- ==>
myfunc = [y | x <- [True], y <- show x]
Run Code Online (Sandbox Code Playgroud)
在列表理解中,x <- [True]
实际上与 相同let x = True
,因为您只从列表中绘制一个元素。所以
myfunc = [y | y <- show True]
Run Code Online (Sandbox Code Playgroud)
当然,“所有的清单y
,以便y
在show True
”就是show True
。
归档时间: |
|
查看次数: |
173 次 |
最近记录: |