我知道 Haskell 的
do
x <- [1, 2, 3]
y <- [7, 8, 9]
let z = (x + y)
return z
可以在 Scala 中表示为
for {
x <- List(1, 2, 3)
y <- List(7, 8, 9)
z = x + y
} yield z
但是,特别是对于 monad,Haskell 经常在do
块内有不对应于<-
or的语句=
。例如,下面是 Pandoc 的一些代码,它使用 Parsec 从字符串中解析某些内容。
-- | Parse contents of 'str' using 'parser' and return result.
parseFromString :: GenParser tok st a -> [tok] -> GenParser tok st a
parseFromString parser str = do
oldPos <- getPosition
oldInput <- getInput
setInput str
result <- parser
setInput oldInput
setPosition oldPos
return result
如您所见,它保存位置和输入,在字符串上运行解析器,然后在返回结果之前恢复输入和位置。
我一生无法弄清楚如何将 , 和 翻译setInput str
成setInput oldInput
Scala setPosition oldPos
。我认为如果我只是把无意义的变量放进去,这样我就可以使用了<-
,比如
for {
oldPos <- getPosition
oldInput <- getInput
whyAmIHere <- setInput str
result <- parser
...
} yield result
但我不确定情况是否如此,如果它是正确的,我相信一定有更好的方法来做到这一点。
哦,如果你能回答这个问题,你能再回答一个吗:我必须盯着 Monads 多长时间才能感觉它们不像黑魔法?:-)
谢谢!托德