我和我的一个高中生将尝试将 Haskell 的 Parsec 解析器组合库移植到 Scala 中。(与 Scala 的内置解析库相比,它的优势在于您可以相当轻松地传递状态,因为所有解析器都是单子。)
我遇到的第一个障碍是试图弄清楚 Functor 在 scalaz 中是如何工作的。有人可以解释如何转换这个 Haskell 代码:
data Reply s u a = Ok a !(State s u) ParseError
| Error ParseError
instance Functor (Reply s u) where
fmap f (Ok x s e) = Ok (f x) s e
fmap _ (Error e) = Error e -- XXX
进入 Scala(我假设使用 Scalaz)。我做到了
sealed abstract class Reply[S, U, A]
case class Ok[S, U, A](a: A, state: State[S, U], error: ParseError)
extends Reply[S, U, A]
case class Error[S, U, A](error: ParseError) extends Reply[S, U, A]
并且知道我应该Reply
扩展这个scalaz.Functor
特征,但我不知道该怎么做。(大多数情况下,我无法弄清楚F[_]
参数的作用。)
任何帮助表示赞赏!
谢谢,托德
根据 dflemstr 的回答,我想出了这个:
sealed abstract class Reply[S, U, A]
object Reply {
implicit def ReplyFunctor[S, U] = {
type ReplySU[A] = Reply[S, U, A]
new Functor[ReplySU] {
def fmap[A, B](r: ReplySU[A], f: A => B) = r match {
case Ok(a, state, error) => Ok(f(a), state, error)
case Error(error) => Error[S, U, B](error)
}
}
}
}
case class Ok[S, U, A](a: A, state: State[S, U], error: ParseError)
extends Reply[S, U, A]()
case class Error[S, U, A](error: ParseError) extends Reply[S, U, A]()
我不确定的是那种ReplySU[A]
类型。Functor
Haskell 中的实际是Reply s u
咖喱类型和a
缺少类型。这是我应该如何在 Scala 中做同样的事情,还是我过于复杂了?