【问题标题】:Scala equivalent of Haskell's do-notation (yet again)Scala 相当于 Haskell 的 do-notation(又一次)
【发布时间】:2012-05-13 13:39:19
【问题描述】:

我知道 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 块中包含不对应于 &lt;-= 的语句。例如,下面是 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 strsetInput oldInputsetPosition oldPos 翻译成Scala。我认为如果我只是把无意义的变量放进去,这样我就可以使用&lt;-,就像

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

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

哦,如果你能回答这个问题,你能再回答一个吗:我必须盯着 Monads 多长时间才能感觉它们不像黑魔法? :-)

谢谢! 托德

【问题讨论】:

  • 如果您不打算使用变量,可以将其名称替换为下划线:_ &lt;- setInput str
  • 我猜这是最像 Scala 的方式。
  • 不确定这是否真的可行,但是通过将这些语句移动到 for 的主体,这可能看起来更自然,您可以真正采用程序风格。

标签: scala haskell monads


【解决方案1】:

是的,该翻译是有效的。

do { x &lt;- m; n } 等价于m &gt;&gt;= \x -&gt; ndo { m; n } 等价于m &gt;&gt; n。由于m &gt;&gt; n 被定义为m &gt;&gt;= \_ -&gt; n(其中_ 的意思是“不要将此值绑定到任何东西”),这确实是一个有效的翻译; do { m; n }do { _ &lt;- m; n }do { unusedVariable &lt;- m; n } 相同。

do 块中没有变量绑定的语句会简单地忽略结果,通常是因为没有有意义的结果可言。例如,putStrLn "Hello, world!" 的结果没有什么有趣的,所以你不会将它的结果绑定到变量。

(至于 monad 是黑魔法,你能得到的最好的认识是它们一点也不复杂;试图在它们中找到更深层次的含义通常不是学习它们如何工作的有效方式。它们是只是一个用于编写碰巧特别常见的计算的接口。我建议阅读Typeclassopedia 以深入了解 Haskell 的抽象类型类,尽管您需要阅读一般的 Haskell 介绍才能从中获得更多信息。)

【讨论】:

  • 知道为什么 Scala 不为 &gt;&gt; 提供糖吗?
  • 我认为是因为 scala 以 for 的形式提供了单子理解。也许计算的顺序没有得到维护。编辑:没关系,它似乎被维护了。
  • Monad 上的答案真的很好。这只是一种编程模式。没有什么“黑魔法”。
  • 在 For-comprehension 方面为 scala 做 &gt;&gt; 的糖实际上只是在做 for { _ &lt;- M }
猜你喜欢
  • 2011-11-20
  • 2018-09-05
  • 1970-01-01
  • 2014-03-26
  • 2013-05-19
  • 1970-01-01
  • 2010-11-20
  • 2015-08-22
  • 2021-08-14
相关资源
最近更新 更多