Advertisement
Guest User

Untitled

a guest
May 27th, 2015
275
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.44 KB | None | 0 0
  1. object exp {
  2.  
  3.  
  4. case class Scope(m: Map[Var[_], Exp[_]]) {
  5. def put[T](pair: (Var[T], Exp[T])): Scope = new Scope(m + pair)
  6. def apply[T](v: Var[T]): Either[String, Exp[T]] = m.get(v) match {
  7. case Some(exp) => Right(exp.asInstanceOf[Exp[T]])
  8. case None => Left(s"$v not found. Scope: $m")
  9. }
  10. }
  11. object Scope {
  12. def empty: Scope = Scope(Map.empty)
  13. }
  14.  
  15. sealed trait Exp[A] {
  16. /**
  17. * Either evaluate the Expression, or return an error string
  18. * (about missing Vars is the only thing that can go wrong)
  19. */
  20. private[exp] def run(scope: Scope): Either[String, A]
  21. }
  22. case class Const[A](get: A) extends Exp[A] {
  23. private[exp] def run(scope: Scope) = Right(get)
  24. }
  25. case class Pair[A, B](first: Exp[A], second: Exp[B]) extends Exp[(A, B)] {
  26. private[exp] def run(scope: Scope) = for {
  27. a <- first.run(scope).right
  28. b <- second.run(scope).right
  29. } yield (a, b)
  30. }
  31. case class Apply[B, A](in: Exp[B], fn: Exp[Fn[B, A]]) extends Exp[A] {
  32. private[exp] def run(scope: Scope) = for {
  33. b <- in.run(scope).right
  34. f <- fn.run(scope).right
  35. } yield f.run(b)
  36. }
  37. case class Var[A](name: String) extends Exp[A] {
  38. private[exp] def run(scope: Scope) = for {
  39. a <- scope(this).right
  40. result <- a.run(scope).right
  41. } yield result
  42. }
  43. case class Lambda[A, B](x: Var[A], result: Exp[B]) extends Exp[Fn[A, B]] {
  44. private[exp] def run(scope: Scope) = Right(Fn.LambdaFn(this, scope))
  45. }
  46. // Private Fn class, so we can't write general scala functions
  47. sealed trait Fn[A, B] {
  48. private[exp] def run(a: A): B
  49. }
  50.  
  51. object Exp {
  52. // would not be here in real life, as it is an escape hatch
  53. // instead, we would convert the Exp to code/source that can
  54. // be run elsewhere
  55. def run[A](e: Exp[A]): Either[String, A] = e.run(Scope.empty)
  56.  
  57. implicit class FnExp[A, B](val e: Exp[Fn[A, B]]) extends AnyVal {
  58. def apply(a: Exp[A]): Exp[B] = Apply[A, B](a, e)
  59. def andThen[C](that: Exp[Fn[B, C]]): Exp[Fn[A, C]] = {
  60. val va = Var[A]("a")
  61. val eb = Apply(va, e)
  62. val ec = Apply(eb, that)
  63. Lambda(va, ec)
  64. }
  65. def zip[C](that: Exp[Fn[A, C]]): Exp[Fn[A, (B, C)]] = {
  66. val va = Var[A]("a")
  67. val b = Apply(va, e)
  68. val c = Apply(va, that)
  69. Lambda(va, Pair(b, c))
  70. }
  71. }
  72. }
  73.  
  74. object Fn {
  75. def fst[A, B](p: Exp[(A, B)]): Exp[A] =
  76. Apply(p, lift(Fst[A, B]()))
  77. def snd[A, B](p: Exp[(A, B)]): Exp[B] =
  78. Apply(p, lift(Snd[A, B]()))
  79. def addInt(a: Exp[Int], b: Exp[Int]): Exp[Int] =
  80. Apply(Pair(a, b), lift(AddInt))
  81.  
  82. def ifThenElse[A](b: Exp[Boolean], iftrue: Exp[A], iffalse: Exp[A]): Exp[A] =
  83. Apply(Pair(b, Pair(iftrue, iffalse)), lift(IfThenElse[A]()))
  84.  
  85. // non fundamental ops
  86. def lift[A, B](f: Fn[A, B]): Exp[Fn[A, B]] = Const(f)
  87. def swap[A, B](p: Exp[(A, B)]): Exp[(B, A)] =
  88. Pair(snd(p), fst(p))
  89.  
  90. def curry[A, B, C](fn: Exp[Fn[(A, B), C]]): Exp[Fn[A, Fn[B, C]]] = {
  91. val a = Var[A]("A")
  92. val b = Var[B]("B")
  93. val pair = Pair(a, b)
  94. val c = Apply(pair, fn)
  95. val fnbc = Lambda(b, c)
  96. Lambda(a, fnbc)
  97. }
  98. def uncurry[A, B, C](fn: Exp[Fn[A, Fn[B, C]]]): Exp[Fn[(A, B), C]] = {
  99. val pair = Var[(A, B)]("pair")
  100. val a = fst(pair)
  101. val fnbc = Apply(a, fn)
  102. val b = snd(pair)
  103. val c = Apply(b, fnbc)
  104. Lambda(pair, c)
  105. }
  106.  
  107. // implementations
  108. private[exp] case class LambdaFn[A, B](l: Lambda[A, B], scope: Scope) extends Fn[A, B] {
  109. def run(a: A) = {
  110. val newScope = scope.put(l.x -> Const(a))
  111. val b = l.result.run(newScope)
  112. b.right.get
  113. }
  114. }
  115. private case class Fst[A, B]() extends Fn[(A, B), A] {
  116. def run(b: (A, B)) = b._1
  117. }
  118. private case class Snd[A, B]() extends Fn[(A, B), B] {
  119. def run(b: (A, B)) = b._2
  120. }
  121. private case object AddInt extends Fn[(Int, Int), Int] {
  122. def run(p: (Int, Int)) = p._1 + p._2
  123. }
  124. private case class IfThenElse[A]() extends Fn[(Boolean, (A, A)), A] {
  125. def run(in: (Boolean, (A, A))) = if(in._1) in._2._1 else in._2._2
  126. }
  127. }
  128.  
  129. }
  130.  
  131. /**
  132. in the repl:
  133. scala> :load expression.scala
  134. Loading expression.scala...
  135. defined module exp
  136.  
  137. scala> import exp._
  138. import exp._
  139.  
  140. scala> Fn.ifThenElse(Const(true), Const(1), Const(2))
  141. res16: exp.Exp[Int] = Apply(Pair(Const(true),Pair(Const(1),Const(2))),Const(IfThenElse()))
  142.  
  143. scala> Exp.run(res16)
  144. res17: Either[String,Int] = Right(1)
  145.  
  146. scala> Fn.ifThenElse(Const(false), Const(1), Const(2))
  147. res18: exp.Exp[Int] = Apply(Pair(Const(false),Pair(Const(1),Const(2))),Const(IfThenElse()))
  148.  
  149. scala> Exp.run(res18)
  150. res19: Either[String,Int] = Right(2)
  151.  
  152. scala> Exp.run(Var("yo"))
  153. res21: Either[String,Nothing] = Left(Var(yo) not found. Scope: Map())
  154. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement