我正在尝试实现一个将字符串转换为Maybe Ints列表的函数,例如readInts "1 2 42 foo" = [Just 1,Just 2,Just 42,Nothing]
。
我的第一个方法是:
readInts (s::String) = do {
ws <- words s;
return (map (readMaybe::(String -> Maybe Int)) ws)
}
这导致以下错误:
lab_monad.hs:20:52:
Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [String]
Actual type: String
In the second argument of ‘map’, namely ‘ws’
In the first argument of ‘return’, namely
‘(map (readMaybe :: String -> Maybe Int) ws)’
Failed, modules loaded: none.
我接下来尝试过(和工作过),是:
readInts (s::String) = do {
let ws = (words s) in do
return (map (readMaybe::(String -> Maybe Int)) ws)
}
我的问题是,words s
显然属于[String]
类型。为什么口译员说它是String
?我对<-
运营商的理解不明白?
答案 0 :(得分:5)
ws <- words s
非确定性地将一个字从words s
分配给ws
;剩下的代码只适用于那个单词,return
函数&#34;神奇地&#34;将所有单词的结果合并到结果列表中。
readInts s = do
ws <- words s -- ws represents *each* word in words s
return (readMaybe ws)
do
符号只是使用monadic bind
的语法糖:
readInts s = words s >>= (\ws -> return (readMaybe ws))
不使用列表的Monad
实例,您可以使用map
将相同的函数应用于每个单词。
readInts s = map readMaybe (words s)
另一方面, let
只是为另一个表达式中使用的更复杂的表达式提供了一个名称。它可以被认为是用于定义和立即应用匿名函数的语法糖。也就是说,
let x = y + z in f x
相当于
(\x -> f x) (y + z)
^ ^ ^
| | |
| | RHS of let binding
| part after "in"
LHS of let binding
具有多个绑定的let
语句等同于嵌套的let
语句:
let x = y + z
a = b + c
in x + a
相当于
let x = y + z
in let a = b + c
in x + a
哪个去了
(\x -> (\a -> x + a)(b + c))(y + z)