斯卡拉相当于Haskell的DO-符号的(再次)(Scala equivalent of Haske

2019-07-29 06:15发布

我知道,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

但是,特别是与单子,Haskell中往往具有内部的语句do块不对应于任一<-= 。 例如,下面是从Pandoc一些代码,使用秒差距解析字符串中的东西。

-- | 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到斯卡拉。 我想,如果我只是把废话变量,所以我可以用它的工作<-

for {
  oldPos <- getPosition
  oldInput <- getInput
  whyAmIHere <- setInput str
  result <- parser
  ...
} yield result

但我不知道是这样的话,如果它是正确的,我敢肯定,必须有一个更好的方式来做到这一点。

哦,如果你能回答这个问题,你能回答一个更:我有多久的单子盯着他们不喜欢黑魔法面前? :-)

谢谢! 托德

Answer 1:

是的,翻译是有效的。

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!" ,这样你就不会其结果绑定到一个变量。

(至于单子是黑魔法,你可以有最好的认识是,他们并不是真正的复杂可言;试图寻找更深层的含义在其中不是一般的学习他们是如何工作的一个有效的方式他们是简单的界面撰写这恰巧是特别常见的计算。我建议你阅读Typeclassopedia获得对Haskell的抽象类型类扎实掌握,但你需要已经阅读一般Haskell的介绍得到离谱了吧。)



文章来源: Scala equivalent of Haskell's do-notation (yet again)