Один из моих старшеклассников и я собираемся сделать порт библиотеки комбинатора парсера Parsec для Haskell на 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, или я слишком усложняю?