我知道哈斯克尔
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但是,尤其是在monads中,Haskell经常在do块中包含与<-或=都不对应的语句。例如,下面是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和setPosition oldPos转换成Scala。我想如果我只是把无意义的变量放进去,这样我就可以使用<-,比如
for {
oldPos <- getPosition
oldInput <- getInput
whyAmIHere <- setInput str
result <- parser
...
} yield result但我不确定情况是否如此,如果它是正确的,我相信肯定有更好的方法来做到这一点。
哦,如果你能回答这个问题,你能再回答一个:我必须盯着单子看多久,它们才不会感觉像黑魔法?:-)
谢谢!托德
发布于 2012-05-04 09:45:28
是的,这个翻译是有效的。
do { x <- m; n }等同于m >>= \x -> n,do { m; n }等同于m >> n。因为m >> n被定义为m >>= \_ -> n (其中_的意思是“不要将这个值绑定到任何东西”),所以这确实是一个有效的翻译;do { m; n }与do { _ <- m; n }或do { unusedVariable <- m; n }相同。
在do块中没有变量绑定的语句完全忽略结果,通常是因为没有什么有意义的结果可言。例如,putStrLn "Hello, world!"的结果没有什么有趣的地方,所以您不会将它的结果绑定到变量。
(至于单子是黑魔法,你能有的最好的认识是它们根本不是真正复杂的;试图在它们中找到更深层次的含义通常不是学习它们如何工作的有效方法。它们只是一个接口,用来编写碰巧特别常见的计算。我建议阅读Typeclassopedia以更好地掌握Haskell的抽象类型类,尽管您需要阅读一般的Haskell介绍才能从中获得更多信息。)
https://stackoverflow.com/questions/10441559
复制相似问题