![](/img/trans.png)
[英]Equivalent of Haskell do-notation or F# Computation Expressions in Scala?
[英]Scala equivalent of Haskell's do-notation (yet again)
我知道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
块中包含与<-
或=
不对应的语句。 例如,这里有一些来自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
但我不确定是不是这样,如果是正确的话,我确信必须有更好的方法来做到这一点。
哦,如果你能回答这个问题,你能再回答一下:在他们感觉不到黑魔法之前,我要多久盯着Monads? :-)
谢谢! 托德
是的,该翻译是有效的。
do { x <- m; n }
do { x <- m; n }
相当于m >>= \\x -> n
,并且do { m; n }
do { m; n }
相当于m >> n
。 由于m >> n
被定义为m >>= \\_ -> n
(其中_
表示“不将此值绑定到任何东西”),这确实是一个有效的翻译; do { m; n }
do { m; n }
与do { _ <- m; n }
do { _ <- m; n }
,或do { unusedVariable <- m; n }
do { unusedVariable <- m; n }
。
在do
块中没有变量绑定的语句只是忽略了结果,通常是因为没有有意义的结果可言。 例如, putStrLn "Hello, world!"
的结果putStrLn "Hello, world!"
,所以你不会将其结果绑定到变量。
(至于monads是黑魔法,你可以拥有的最好的实现是它们根本不是真的很复杂;试图在它们中找到更深层的含义通常不是学习它们如何工作的有效方式。它们只是一个界面编写碰巧特别常见的计算。我建议阅读Typeclassopedia来掌握Haskell的抽象类型类,尽管你需要阅读一般的Haskell介绍才能从中获得更多。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.