Created
June 28, 2017 12:20
-
-
Save manuelleduc/6dc31cd246c2f95a54ef84822dc2df84 to your computer and use it in GitHub Desktop.
Modular visitor in scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package modularexp | |
import scala.language.higherKinds | |
/** | |
* Created by mleduc on 28/06/17. | |
*/ | |
trait Exp[A] | |
trait Sum[A] extends Exp[A] { | |
val lhs: Exp[A] with A | |
val rhs: Exp[A] with A | |
} | |
trait Const[A] extends Exp[A] { | |
val value: Int | |
} | |
trait VisitorSum[A] { | |
def visitSum(e: Sum[Acceptor[A]]): A | |
} | |
trait VisitorConst[A] { | |
def visitConst(e: Const[Acceptor[A]]): A | |
} | |
trait Acceptor[A] { | |
def accept(): A | |
} | |
class PrettyPrintVisitor extends VisitorConst[String] with VisitorSum[String] { | |
override def visitConst(e: Const[Acceptor[String]]): String = e.value.toString | |
override def visitSum(e: Sum[Acceptor[String]]): String = s"(${e.lhs.accept()} + ${e.rhs.accept()})" | |
} | |
trait CalculateVisitorConst extends VisitorConst[Int] { | |
override def visitConst(e: Const[Acceptor[Int]]): Int = e.value | |
} | |
trait CalculateVisitorSum extends VisitorSum[Int] { | |
override def visitSum(e: Sum[Acceptor[Int]]): Int = e.lhs.accept() + e.rhs.accept() | |
} | |
object Test extends App { | |
val ppv = new PrettyPrintVisitor | |
def program[A](ppv: VisitorSum[A] with VisitorConst[A]): Sum[Acceptor[A]] with Acceptor[A] = { | |
val buildSum = initBuildSum(ppv) | |
val buildConst = initBuildConst(ppv) | |
val lhs = buildConst(1) | |
val rhs = buildConst(2) | |
val program = buildSum(lhs, rhs) | |
program | |
} | |
def initBuildSum[A](ppv: VisitorSum[A]): (Exp[Acceptor[A]] with Acceptor[A], Exp[Acceptor[A]] with Acceptor[A]) => Sum[Acceptor[A]] with Acceptor[A] = (lhs_, rhs_) => { | |
new Sum[Acceptor[A]] with Acceptor[A] { | |
override val lhs: Exp[Acceptor[A]] with Acceptor[A] = lhs_ | |
override val rhs: Exp[Acceptor[A]] with Acceptor[A] = rhs_ | |
override def accept() = ppv.visitSum(new Sum[Acceptor[A]] { | |
override val lhs: Exp[Acceptor[A]] with Acceptor[A] = lhs_ | |
override val rhs: Exp[Acceptor[A]] with Acceptor[A] = rhs_ | |
}) | |
} | |
} | |
def initBuildConst[A](ppv: VisitorConst[A]): (Int) => Const[Acceptor[A]] with Acceptor[A] = (nbr) => { | |
new Const[Acceptor[A]] with Acceptor[A] { | |
override val value: Int = nbr | |
override def accept(): A = ppv.visitConst(new Const[Acceptor[A]] { | |
override val value: Int = nbr | |
}) | |
} | |
} | |
println(program(ppv).accept()) | |
println(program(new CalculateVisitorConst with CalculateVisitorSum {}).accept()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment