【发布时间】:2012-03-30 10:25:02
【问题描述】:
我和我的一个高中生打算尝试将 Haskell 的 Parsec 解析器组合器库移植到 Scala 中。 (与 Scala 的内置解析库相比,它的优势在于您可以相当轻松地传递状态,因为所有解析器都是 monad。)
我遇到的第一个问题是试图弄清楚 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] 类型。 Haskell 中实际的Functor 是Reply s u,带有咖喱类型,而a 类型缺失。这是我应该如何在 Scala 中做同样的事情,还是我过于复杂了?
【问题讨论】:
-
Scala 解析器也是单子! Scala monad 是任何具有
map和flatMap方法实现的对象(只要它们满足 monad 公理)。 -
看起来您已经得到了答案,但对于未来,请随时加入。irc://freenode.net/#scalaz
标签: scala haskell functor scalaz