Skip to content

Instantly share code, notes, and snippets.

@joshcough
Last active October 29, 2015 17:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshcough/bc9050a42630008b1eed to your computer and use it in GitHub Desktop.
Save joshcough/bc9050a42630008b1eed to your computer and use it in GitHub Desktop.
object LetLangError {
import scala.language.higherKinds
import scalaz.MonadError
import scalaz.syntax.monad._
import scalaz.syntax.monadError._
trait Exp
case class Num(i:Int) extends Exp
case class Add (l:Exp, r:Exp) extends Exp
case class Mult(l:Exp, r:Exp) extends Exp
case class Var (v: String) extends Exp
case class Let (v: (String, Exp), body:Exp) extends Exp
type Env = Map[String, Int]
implicit class Parser(val sc: StringContext) extends AnyVal {
def v(args: Any*): Var = Var(sc.parts.mkString)
def n(args: Any*): Num = Num(sc.parts.mkString.toInt)
}
def lookup[F[_,_]](v: String, env: Env)
(implicit m: MonadError[F, String]): F[String, Int] =
env.get(v).fold[F[String, Int]](
s"unbound variable $v".raiseError[F,Int])((i: Int) => m.point(i))
def interp[F[_,_]](node: Exp, env: Env=Map())
(implicit m: MonadError[F, String]): F[String, Int] =
node match {
case Num (i) => m.point(i)
case Add (l,r) => for {
ll <- interp(l,env)
rr <- interp(r,env)
} yield ll + rr
case Mult(l,r) => for {
ll <- interp(l,env)
rr <- interp(r,env)
} yield ll * rr
case Var (v) => lookup(v, env)
case Let ((x,e),b) => for {
eValue <- interp(e, env)
z <- interp(b, env + (x -> eValue))
} yield z
}
def run[F[_,_]](node: Exp, expected: F[String, Int])
(implicit m: MonadError[F, String]): F[String, Int] = {
val i = interp(node)
if(i!=expected) sys.error(s"expected: $expected, but got: $i")
i
}
def main(args: Array[String]): Unit = {
import scalaz.{\/,WriterT}, WriterT._
import scalaz.Scalaz._
println(run[\/](Num(6), 6.right))
println(run[\/](Var("x"), "unbound variable x".left))
println(run[Either](Num(6), Right(6)))
println(run[Either](Var("x"), Left("unbound variable x")))
// println(run[WriterT[List, ?, ?]](Num(6), ???))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment