One of my high school students and I are going to try to do a port of Haskell's Parsec parser combinator library into Scala. (It has the advantage over Scala's built-in parsing library that you can pass state around fairly easily because all the parsers are monads.)
The first hitch I've come across is trying to figure out how Functor works in scalaz. Can someone explain how to convert this Haskell code:
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
into Scala (using Scalaz, I assume). I got as far as
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]
and know that I should make Reply
extend the scalaz.Functor
trait, but I can't figure out how to do that. (Mostly I'm having trouble figuring out what the F[_]
parameter does.)
Any help appreciated!
Thanks, Todd
Based on dflemstr's answer, I came up with this:
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]()
What I'm not sure about is that ReplySU[A]
type. The actual Functor
in Haskell is Reply s u
with curried types and the a
type missing. Is this how I should do the same thing in Scala or am I overly complicating things?
map
andflatMap
methods (provided they satisfy monad axioms). – paradigmatic