简体   繁体   English

Scala相当于Haskell的记号(再次)

[英]Scala equivalent of Haskell's do-notation (yet again)

I know that Haskell's 我知道Haskell的

do
  x <- [1, 2, 3]
  y <- [7, 8, 9]
  let z = (x + y)
  return z

can be expressed in Scala as 可以用Scala表示为

for {
  x <- List(1, 2, 3)
  y <- List(7, 8, 9)
  z = x + y
} yield z

But, especially with monads, Haskell often has statements inside the do block that don't correspond to either <- or = . 但是,尤其是对于monad,Haskell通常在do块中包含与<-=不对应的语句。 For example, here's some code from Pandoc that uses Parsec to parse something from a string. 例如,这里有一些来自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

As you can see, it saves the position and input, runs the parser on the string, and then restores the input and position before returning the result. 如您所见,它保存位置和输入,在字符串上运行解析器,然后在返回结果之前恢复输入和位置。

I can't for the life of me figure out how to translate setInput str , setInput oldInput , and setPosition oldPos into Scala. 我不能为我的生活弄清楚如何将setInput strsetInput oldInputsetPosition oldPos转换为Scala。 I think it would work if I just put nonsense variables in so I could use <- , like 我认为如果我只是把无意义的变量放入其中就可以了,所以我可以使用<- ,就像

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

but I'm not sure that's the case and, if it is correct, I'm sure that there must be a better way to do this. 但我不确定是不是这样,如果是正确的话,我确信必须有更好的方法来做到这一点。

Oh, and if you can answer this question, can you answer one more: how long do I have to stare at Monads before they don't feel like black magic? 哦,如果你能回答这个问题,你能再回答一下:在他们感觉不到黑魔法之前,我要多久盯着Monads? :-) :-)

Thanks! 谢谢! Todd 托德

Yes, that translation is valid. 是的,该翻译是有效的。

do { x <- m; n } do { x <- m; n } is equivalent to m >>= \\x -> n , and do { m; n } do { x <- m; n }相当于m >>= \\x -> n ,并且do { m; n } do { m; n } is equivalent to m >> n . do { m; n }相当于m >> n Since m >> n is defined as m >>= \\_ -> n (where _ means "don't bind this value to anything"), that is indeed a valid translation; 由于m >> n被定义为m >>= \\_ -> n (其中_表示“不将此值绑定到任何东西”),这确实是一个有效的翻译; do { m; n } do { m; n } is the same as do { _ <- m; n } do { m; n }do { _ <- m; n } do { _ <- m; n } , or do { unusedVariable <- m; n } do { _ <- m; n } ,或do { unusedVariable <- m; n } do { unusedVariable <- m; n } . do { unusedVariable <- m; n }

A statement without a variable binding in a do block simply disregards the result, usually because there's no meaningful result to speak of. do块中没有变量绑定的语句只是忽略了结果,通常是因为没有有意义的结果可言。 For instance, there's nothing interesting to do with the result of putStrLn "Hello, world!" 例如, putStrLn "Hello, world!"的结果putStrLn "Hello, world!" , so you wouldn't bind its result to a variable. ,所以你不会将其结果绑定到变量。

(As for monads being black magic, the best realisation you can have is that they're not really complicated at all; trying to find deeper meaning in them is not generally a productive way of learning how they work. They're simply an interface to compose computations that happen to be particularly common. I recommend reading the Typeclassopedia to get a solid grasp on Haskell's abstract typeclasses, though you'll need to have read a general Haskell introduction to get much out of it.) (至于monads是黑魔法,你可以拥有的最好的实现是它们根本不是真的很复杂;试图在它们中找到更深层的含义通常不是学习它们如何工作的有效方式。它们只是一个界面编写碰巧特别常见的计算。我建议阅读Typeclassopedia来掌握Haskell的抽象类型类,尽管你需要阅读一般的Haskell介绍才能从中获得更多。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM