I wanted to know in a pattern matching, like in the following, do we say that the case classes are bound dynamically or statically?
sealed trait Expr
case class Lit(n: Int) extends Expr
case class Add(l: Expr, r: Expr) extends Expr
class Eval {
def eval(e: Expr): Int = e match {
case Lit(n) => n
case Add(l, r) => eval(l) + eval(r)
}
}
class Printo {
def printo(e: Expr): Unit = e match {
case Lit(n) => print(" " + n + " ")
case Add(l, r) => printo(l); print("+"); printo(r)
}
}
//Test
object TestExpr {
def main(args: Array[String]) {
val eval = new Eval
val printo = new Printo
val expr1 =
Add(Add(Lit(4), Add(Lit(7), Lit(10))),
Add(Lit(4), Add(Lit(7), Lit(10))))
val x = eval.eval(expr1)
p + "" + println(" = " + x)
}
}
How I can know if the Lit(n) or Add(l, r) are called / bound statically or dynamically?
Related
I am trying to adapt this Haskell implementation of the type classes based solution of the expression problem to Scala. My current code is below. I'm having problems expressing the existential type Exp in Scala.
How can I achieve the same thing?
object ExpressionProblem {
// class Eval a where
// eval :: a -> Int
trait Eval[A] {
def eval(expr: A): Int
}
// data Exp = forall t. Eval t => Expr t
sealed abstract class Exp
case class Expr[T](val e: T)(implicit ev: Eval[T]) extends Exp
// instance Eval Exp where
// eval (Expr e) = eval e
implicit val exprInstance = new Eval[Exp] {
def eval(expr: Exp) = expr match { case Expr(e, ev) => ev.eval(e) }
}
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// here is the problem
// data BaseExp = Const Int | Add Exp Exp | Mul Exp Exp
sealed abstract class BaseExpr
case class Const(c: Int) extends BaseExpr
case class Add(lhs: Exp, rhs: Exp) extends BaseExpr
case class Mul(lhs: Exp, rhs: Exp) extends BaseExpr
// instance Eval BaseExp where
// eval (Const n) = n
// eval (Add a b) = eval a + eval b
// eval (Mul a b) = eval a * eval b
implicit val baseExprInstance = new Eval[BaseExpr] {
def eval(baseExpr: BaseExpr)(implicit e: Eval[Exp]): Int =
baseExpr match {
case Const(c) => c
case Add(lhs, rhs) => e.eval(lhs) + e.eval(rhs)
case Mul(lhs, rhs) => e.eval(lhs) + e.eval(rhs)
}
}
// TODO: Is there an easier way to make all of them implicitly convertible?
//
// The following doesn't seem to work:
//
// implicit def baseExprToExp[T <: BaseExpr](t: T): Exp = Expr[BaseExpr](t)
//
implicit def constToExp(c: Const): Exp = Expr[BaseExpr](c)
implicit def addToExp(a: Add): Exp = Expr[BaseExpr](a)
implicit def mulToExp(m: Mul): Exp = Expr[BaseExpr](m)
///////////////////////////////////////////////
// Possibly in another module/lib.
///////////////////////////////////////////////
// data SubExp = Sub Exp Exp
case class SubExpr(val lhs: Exp, val rhs: Exp)
// instance Eval SubExp where
// eval (Sub a b) = eval a - eval b
implicit val subExprInstance = new Eval[SubExpr] {
def eval(subExpr: SubExpr)(implicit e: Eval[Exp]): Int =
e.eval(subExpr.lhs) - e.eval(subExpr.rhs)
}
// Make it implicitly convertible to Exp.
implicit def subExprToExp(s: SubExpr): Exp = Expr(s)
object Test {
val exprs: List[Exp] = List(
SubExpr(Const(10), Const(3)),
Add(Const(1), Const(1))
)
}
} // ExpressionProblem
EDIT: Meanwhile I found this relevant StackOverflow answer and I adapted my code to it.
import scala.language.implicitConversions
object ExpressionProblem {
// class Eval a where
// eval :: a -> Int
trait Eval[A] {
def eval(expr: A): Int
}
//////////////////////////////////////////
// HERE'S THE MAGIC
//
// data Expr = forall t. Eval t => Expr t
trait Expr {
type T
val t: T
val evalInst: Eval[T]
}
object Expr {
def apply[T0 : Eval](t0: T0) = new Expr {
type T = T0
val t = t0
val evalInst = implicitly[Eval[T]]
}
}
// Default boxing is needed
implicit def box[T : Eval](t: T) = Expr(t)
// instance Eval Expr where
// eval (Expr e) = eval e
implicit object exprInstance extends Eval[Expr] {
def eval(expr: Expr) = expr.evalInst.eval(expr.t)
}
// data BaseExpr = Const Int | Add Expr Expr | Mul Expr Exp
sealed abstract class BaseExpr
case class Const(c: Int) extends BaseExpr
case class Add(lhs: Expr, rhs: Expr) extends BaseExpr
case class Mul(lhs: Expr, rhs: Expr) extends BaseExpr
// instance Eval BaseExpr where
// eval (Const n) = n
// eval (Add a b) = eval a + eval b
// eval (Mul a b) = eval a * eval b
implicit object baseExprInstance extends Eval[BaseExpr] {
def eval(baseExpr: BaseExpr): Int =
baseExpr match {
case Const(c) => c
case Add(lhs, rhs) => exprInstance.eval(lhs) + exprInstance.eval(rhs)
case Mul(lhs, rhs) => exprInstance.eval(lhs) + exprInstance.eval(rhs)
}
}
// Implicit conversions for all base expressions
implicit def baseExprToExpr[T <: BaseExpr](t: T): Expr = Expr[BaseExpr](t)
///////////////////////////////////////////////
// Possibly somewhere else (in the future).
///////////////////////////////////////////////
// data SubExpr = Sub Expr Exp
case class SubExpr(val lhs: Expr, val rhs: Expr)
// instance Eval SubExpr where
// eval (Sub a b) = eval a - eval b
implicit object subExprInstance extends Eval[SubExpr] {
def eval(subExpr: SubExpr): Int =
exprInstance.eval(subExpr.lhs) - exprInstance.eval(subExpr.rhs)
}
// NOTE: We don't have to provide an implicit conversion to Expr as the
// default `box` one suffices.
object Test {
val exprs: List[Expr] = List(
SubExpr(Const(10), Const(3)),
Add(Const(1), Const(1))
)
}
} // ExpressionProblem
Your problem is that you are using an extractor (unapply), but neglecting the fact that implicits are not by default exposed as part of unapply.
So this line:
def eval(expr: Exp) = expr match { case Expr(e, ev) => ev.eval(e) }
There is no case Expr(e, ev), only case Expr(e), because only e is exposed. Either write a custom extractor or find a different approach.
Scala does offer existential types of the form:
Expr[T] forSome { type T})
That has a shorthand type notation available: Expr[_]
Your code has a few more issues though:
If you define an implicit on eval, all implementors must implement an eval function with that particular signature, you can't override eval with an implementation that doesn't contain the implicit in the signature like you do in.
implicit val baseExprInstance = new Eval[BaseExpr] {
def eval(baseExpr: BaseExpr)(implicit e: Eval[Exp]): Int =
baseExpr match {
case Const(c) => c
case Add(lhs, rhs) => e.eval(lhs) + e.eval(rhs)
case Mul(lhs, rhs) => e.eval(lhs) + e.eval(rhs)
}
}
Next up you are going to need to either make T on Expr contravariant or make SubExpr also extend Exp, you have a problem here:
// instance Eval SubExp where
// eval (Sub a b) = eval a - eval b
implicit val subExprInstance = new Eval[SubExpr] {
def eval(subExpr: SubExpr)(implicit e: Eval[SubExpr]): Int =
e.eval(subExpr.lhs) - e.eval(subExpr.rhs)
}
If you will try to match the type signature, implicit e: Eval[SubExpr] can eval types that are T >: SubExpr, but what you require is a lower Exp implicit for Eval.
I'm learning Scala and the following simple program got me stuck:
class ObjectPrinter[T <: AnyVal](x: T) {
def print(t: T) = { // <--- error here
case Is(i) => println("Integer: " + i)
case Ds(d) => println("Double: " + d)
case _ => println("Default")
}
case class Is(i : Int) extends ObjectPrinter[Int](i);
case class Ds(d: Double) extends ObjectPrinter[Double](d);
}
The error message is the following:
Missing type parameter for expanded function. The argument type of an
anonymous function must be fully known. Expected type was: ?
The message is completely unclear to me. What do they mean, missing type parameter? I thought the type parameter follows after the case, like Is(i). What function is expanded?
UPD: I want to return a function depending on the type of the argument passed in as a parameter.
{
case Is(i) => println("Integer: " + i)
case Ds(d) => println("Double: " + d)
case _ => println("Default")
}
is short for
y => y match {
case Is(i) => println("Integer: " + i)
case Ds(d) => println("Double: " + d)
case _ => println("Default")
}
(that's the expanded function the error is talking about. But the compiler has no way to tell what do you want y's type to be.
If this is what you want, the simplest way to specify the type would be
(_: SomeType) match {
case Is(i) => println("Integer: " + i)
case Ds(d) => println("Double: " + d)
case _ => println("Default")
}
But this looks quite strange: you are using neither x nor t there.
I would implement it through typeclass
case class ObjectPrinter[T <: AnyVal](x: T)
object ObjectPrinter {
implicit val printInt = new Print[Int] {
override def print(t: ObjectPrinter[Int]): Unit = println("Integer: " + t.x)
}
implicit val printDouble = new Print[Double] {
override def print(t: ObjectPrinter[Double]): Unit = println("Double: " + t.x)
}
def print[T <: AnyVal](t: ObjectPrinter[T])(implicit print: Print[T]) = {
print.print(t)
}
}
trait Print[T <: AnyVal] {
def print(t: ObjectPrinter[T]): Unit
}
Alternatively, this one - compiles
class ObjectPrinter[T <: AnyVal](x: T) {
def print(t: T): Unit = t match {
case i: Int => println("Integer: " + i)
case d: Double => println("Double: " + d)
case _ => println("Default")
}
case class Is(i : Int) extends ObjectPrinter[Int](i);
case class Ds(d: Double) extends ObjectPrinter[Double](d);
}
(though I do not see any usecase how you would use print, i.e. why do you enforce t and x be the same type)
May be you meant to have such implementation:
class ObjectPrinter[T <: AnyVal](x: T)
object ObjectPrinter {
def print[T <: AnyVal](op: ObjectPrinter[T]): Unit = op match { // <--- error here
case Is(i: Int) => println("Integer: " + i)
case Ds(d: Double) => println("Double: " + d)
case _ => println("Default")
}
}
case class Is(i : Int) extends ObjectPrinter[Int](i)
case class Ds(d: Double) extends ObjectPrinter[Double](d)
object Test extends App {
ObjectPrinter.print(Is(5))
}
I'm playing with pattern matching, but I have some difficult to understand what's wrong with this piece of code:
class Expr {
case class Number(v : Int) extends Expr
case class Sum(a : Expr, b : Expr) extends Expr
def show(e: Expr): String = {
e match {
case Number(a) => a.toString()
case Sum(a, b) => "(" + show(a) + "+" + show(b) + ")"
}
}
override def toString() = show(this)
}
class Number(v : Int) extends Expr
class Sum(a : Expr, b : Expr) extends Expr
object Number {
def apply(v : Int) = new Number(v)
}
object Sum extends Expr {
def apply(a : Expr, b : Expr) = new Sum(a, b)
}
object ExpressionProblem {
def main(args: Array[String]) {
val p = Sum( Number(3), Number(4))
println( p )
}
}
When I try to execute println it throws a MatchError.
Exception in thread "main" scala.MatchError: an instance of class week4.Expr$Sum
at week4.Expr.show(ExpressionProblem.scala:8)
at week4.Expr.toString(ExpressionProblem.scala:14)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at scala.Console$.println(Console.scala:148)
at scala.Predef$.println(Predef.scala:315)
at week4.ExpressionProblem$.main(ExpressionProblem.scala:31)
at week4.ExpressionProblem.main(ExpressionProblem.scala)
you're sending an instance of your Sum class, but trying to match an instance of Sum case class. Remove classes and make case classes visible to your code:
trait Expr {
def show(e: Expr): String = e match {
case Number(a) => a.toString()
case Sum(a, b) => "(" + show(a) + "+" + show(b) + ")"
}
override def toString() = show(this)
}
case class Number(v : Int) extends Expr
case class Sum(a : Expr, b : Expr) extends Expr
object ExpressionNoProblem {
def main(args: Array[String]) {
val p = Sum(Number(3), Number(4))
println(p)
}
}
Example code snippet :
def evalExpr(e: Expr): Int = e match {
case Num(n) => n
case Sum(l, r) => evalExpr(l) + evalExpr(r)
case Prod(l, r) => evalExpr(l) * evalExpr(r)
}
What would be the best way to implement pattern matching where evalExpr runs asynchronously?
You can Wrap them in Scala's Futures :
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
trait Expr
case class Num(n:Int) extends Expr
case class Sum(n:Expr,m:Expr) extends Expr
case class Prod(n:Expr,m:Expr) extends Expr
def evalExpr(e: Expr): Future[Int] = e match {
case Num(n) => Future(n)
case Sum(l, r) =>
val exp1 = evalExpr(l)
val exp2 = evalExpr(r)
for{
i<-exp1
j<-exp2
} yield i + j
case Prod(l, r) =>
val exp1 = evalExpr(l)
val exp2 = evalExpr(r)
for{
i<-exp1
j<-exp2
} yield i + j
}
evalExpr(Prod(Sum(Num(1),Prod(Num(3),Num(2))),Num(2))).map(println)
scala> evalExpr(Prod(Sum(Num(1),Prod(Num(3),Num(2))),Num(2))).map(println)
8 // As you can see output of the calculation is asynchronously printed.
res0: scala.concurrent.Future[Unit] = scala.concurrent.impl.Promise$DefaultPromise#65039982
If the evalExpr(Expr) would return Future[Int] you would write for instance Prod(l, r) like this:
case Prod(l, r) => {
val eval1 = evalExpr(l)
val eval2 = evalExpr(r)
for {
left <- eval1
right <- eval2
} yield left*right
}
This would combine the two futures - left and right - together and return new future.
Using futures also the case Num(n) should be => Future(n).
I want to write a scala program simplifying this mathematical expression using distributivity rule:
a*b+a*c = a(b+c)
I quickly wrote the following code in order to solve this example:
object Test {
sealed abstract class Expr
case class Var(name: String) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr
def main(args: Array[String]) {
val expr = BinOp("+", BinOp("*", Var("a"), Var("b")), BinOp("*", Var("a"), Var("c")))
println(simplify(expr)) //outputs "a(b + c)"
}
def simplify(expr: Expr) : String = expr match {
case BinOp("+", BinOp("*", Var(x), Var(a)), BinOp("*", Var(y), Var(b))) if (x == y) => "" + x + "*(" + a + " + " + b + ")"
case _ => "" //no matter for the test since I test the first case statically
}
}
Is there a better way to achieve this?
What is the best way to manage the order of operand without duplicating cases for each combination (would be ugly...)? Indeed, what about these expressions:
a*b+a*c = a(b+c)
a*b+c*a = a(b+c)
b*a+a*c = a(b+c)
b*a+c*a = a(b+c)
If Expr keeps commutative law, it must be
def simplify(expr: Expr) : String = expr match {
case expr # BinOp("+", BinOp("*", Var(x), Var(a)), BinOp("*", Var(y), Var(b))) => {
def another(that: String) = {
Seq((x, a), (a, x)) find (_._1 == that) map (_._2)
}
val byY = another(y).map(z => BinOp("+", Var(y), BinOp("*", Var(z), Var(b)))) // combine by y
val byB = another(b).map(z => BinOp("+", Var(b), BinOp("*", Var(z), Var(y)))) // combine by b
(byY orElse byB getOrElse expr).toString
}
case _ => "" //no matter for the test since I test the first case statically
}
byY and byB have the same structure. This is not the best, you maybe reuse some piece of code. :P