首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala相当于Haskell的do-notation (再一次)

Scala相当于Haskell的do-notation (再一次)
EN

Stack Overflow用户
提问于 2012-05-04 09:33:49
回答 1查看 4.2K关注 0票数 21

我知道哈斯克尔

代码语言:javascript
复制
do
  x <- [1, 2, 3]
  y <- [7, 8, 9]
  let z = (x + y)
  return z

可以在Scala中表示为

代码语言:javascript
复制
for {
  x <- List(1, 2, 3)
  y <- List(7, 8, 9)
  z = x + y
} yield z

但是,尤其是在monads中,Haskell经常在do块中包含与<-=都不对应的语句。例如,下面是Pandoc的一些代码,它使用Parsec解析字符串中的内容。

代码语言:javascript
复制
-- | 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 strsetInput oldInputsetPosition oldPos转换成Scala。我想如果我只是把无意义的变量放进去,这样我就可以使用<-,比如

代码语言:javascript
复制
for {
  oldPos <- getPosition
  oldInput <- getInput
  whyAmIHere <- setInput str
  result <- parser
  ...
} yield result

但我不确定情况是否如此,如果它是正确的,我相信肯定有更好的方法来做到这一点。

哦,如果你能回答这个问题,你能再回答一个:我必须盯着单子看多久,它们才不会感觉像黑魔法?:-)

谢谢!托德

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-04 09:45:28

是的,这个翻译是有效的。

do { x <- m; n }等同于m >>= \x -> ndo { 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介绍才能从中获得更多信息。)

票数 28
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10441559

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档