First for the easy part is the βstrangeβ import system:
import scalaz._, Scalaz._
It's all. This will always work (of course, to prevent name collisions, but this is possible with any library and is easily resolved), and no one is going to look down on you to not use the new import a la carte, which is mainly related to documentation.
The basic template for monad transformers is that you have a class like WhateverT[F[_], ...] that has a method called runWhateverT (or just run ) that returns F[Whatever[...]] .
In this case, it looks like you want to get a Parser[Exp] , which assumes that you need your own ExpT[F[_]] transformer ExpT[F[_]] . I will not start with details on how to implement this (which, of course, will depend on the semantics of your monad), but will give an example using Scalaz OptionT :
import scala.util.parsing.combinator._ import scalaz._, Scalaz._ object MyParser extends RegexParsers { implicit val monad = parserMonad(this) def oddNumber: OptionT[Parser, Int] = OptionT.optionT( "\\d+".r ^^ (_.toInt) ^^ (i => (i % 2 != 0) option i) ) def pairOfOdds: OptionT[Parser, (Int, Int)] = for { _ <- literal("(").liftM[OptionT] x <- oddNumber _ <- literal(",").liftM[OptionT] y <- oddNumber _ <- literal(")").liftM[OptionT] } yield (x, y) def apply(s: String) = parse(pairOfOdds.run, s) }
See my question here for a discussion of why we need the string implicit val monad = ...
It works as follows:
scala> MyParser("(13, 43)") res0: MyParser.ParseResult[Option[(Int, Int)]] = [1.9] parsed: Some((13,43)) scala> MyParser("(13, 42)") res1: MyParser.ParseResult[Option[(Int, Int)]] = [1.8] parsed: None
Note that oddNumber.run will give us Parser[Option[Int]] , which will parse the string of digits and return either Some(i) (if they represent an odd number) or None (if they are even).
In fact, we will not call oddNumber.run , but in this case, the fact that we are using a monad transformer means that we can create oddNumber with the canceled actions Parser ( literal(...) here) in one sense for .
The syntax here is ugly: we lose the pretty compilers ~ and implicit conversions from String to Parser[String] , but we could easily write canceled versions of these things if we wanted to.