Welcome! Got a question? Do you have -Ypartial-unification turned on? Other FAQs: http://typelevel.org/cats/faq.html
data Op = Add Int Int | Const Int
Op
to whatever you want to interpret this to (e.g. an Int
for evaluation, or a String for pretty printing)
data Exp = Add Exp Exp | Lit Int
sealed trait Exp
case class Add(l: Exp, r: Exp) extends Exp
case class Lit(i: Int) extends Exp
class Exp t where
lit :: Int -> t
add :: t -> t -> t
trait Exp[T] {
def lit(i: Int): T
def add(l: T, r: T): T
}
new Exp[Int] { def lit(i: Int): Int = i def add(l: Int, r: Int): Int = l + r }
def expr[A]: Expr[A] = add(lit(1), add(lit(3), lit(5))
Exp[Int]
, you create a newtype over Int, and use that as your target
haskell
expr: Exp a => a
expr = add(lit(1), add(lit(3), lit(5))
vanilla scala
def expr[A](alg: Exp[A]): A = alg.add(alg.lit(1), alg.add(alg.lit(3), alg.lit(5))
scala with hypothetical full syntax support (a la cats)
def expr[A: Exp]: A = 1.lit.add(3.lit add 5.lit)
def foo[F[_]: Monad, A]: F[A] = ???