Я знаю, что Haskell's
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, который использует 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
но я не уверен, что случай, и если это правильно, я уверен, что должен быть лучший способ сделать это.
О, и если вы можете ответить на этот вопрос, можете ли вы ответить на еще один вопрос: как долго мне нужно смотреть на Монады, прежде чем они не будут чувствовать себя черной магией?: -)
Спасибо! Todd