I have such case classes:
abstract class Tree
case class Sum(l: Tree, r: Tree) extends Tree
case class Var(n: String) extends Tree
case class Const(v: Int) extends Tree
Now i write such object :
object Main {
type Environment = String => Int
def derive(t: Tree, v: String): Tree = t match {
case Sum(l, r) => Sum(derive(l, v), derive(r, v))
case Var(n) if (v == n) => Const(1)
case _ => Const(0)
}
def eval(t: Tree, env: Environment): Int = t match {
case Sum(l, r) => eval(l, env) + eval(r, env)
case Var(n) => env(n)
case Const(v) => v
}
def simple(t: Tree): Const = t match {
case Sum(l, r) if (l.isInstanceOf[Const] && r.isInstanceOf[Const]) => Const(l.asInstanceOf[Const].v + r.asInstanceOf[Const].v)
case Sum(l, r) if (l.isInstanceOf[Sum] && r.isInstanceOf[Sum]) => Const(simple(l).v+ simple(r).v)
case Sum(l, r) if (l.isInstanceOf[Sum]) => Const(simple(l).v + r.asInstanceOf[Const].v)
case Sum(l, r) if (r.isInstanceOf[Sum]) => Const(simple(r).v + l.asInstanceOf[Const].v)
}
def main(args: Array[String]) {
val exp: Tree = Sum(Sum(Var("x"), Var("x")), Sum(Const(7), Var("y")))
val env: Environment = {
case "x" => 5
case "y" => 7
}
println("Expression: " + exp)
println("Evaluation with x=5, y=7: " + eval(exp, env))
println("Derivative relative to x:\n " + derive(exp, "x"))
println("Derivative relative to y:\n " + derive(exp, "y"))
println("Simplified expression:\n" + simple(derive(exp, "x")))
}
}
I am new in scala. Is it possible write method simple with small count of code and maybe in scala way?
Thanks for advice.
You're almost there. In Scala, extractors can be nested:
def simple(t: Tree): Const = t match {
case Sum(Const(v1), Const(v2)) => Const(v1 + v2)
case Sum(s1 # Sum(_,_), s2 # Sum(_, _)) => Const(simple(s1).v+ simple(s2).v)
case Sum(s # Sum(_, _), Const(v)) => Const(simple(s).v + v)
case Sum(Const(v), s # Sum(_, _)) => Const(simple(s).v + v)
}
Of course, this will give you some warnings about incomplete matches, and the sx # Sum(_, _) repeatedly suggests that there may be a better approach that includes matching on Const and Var at the root level and making more recursive calls to simple.
Although this question has been closed, but I think this version should be a better one,
def simplify(t: Tree): Tree = t match {
case Sum(Const(v1), Const(v2)) => Const(v1 + v2)
case Sum(Const(v1), Sum(Const(v2), rr)) => simplify(Sum(Const(v1 + v2), simplify(rr)))
case Sum(l, Const(v)) => simplify(Sum(Const(v), simplify(l)))
case Sum(l, Sum(Const(v), rr)) => simplify(Sum(Const(v), simplify(Sum(l, rr))))
case Sum(Sum(ll, lr), r) => simplify(Sum(ll, simplify(Sum(lr, r))))
case Sum(Var(n), r) => Sum(simplify(r), Var(n))
case _ => t
}
it seems works with "complex" expressions with variables.
Just a small improvement:
def derive(t: Tree, v: String): Tree = t match {
case Sum(l, r) => Sum(derive(l, v), derive(r, v))
case Var(`v`) => Const(1)
case _ => Const(0)
}
How about this:
def simplify(t: Tree): Tree = t match {
case Sum(Const(v1),Const(v2)) => Const(v1+v2)
case Sum(left,right) => simplify(Sum(simplify(left),simplify(right)))
case _ => t //Not necessary, but for completeness
}
Note that it returns a Tree, not a Const, so it should be able to simplify trees with variables too.
I'm learning Scala so any suggestions as to why this wouldn't work etc. are more than welcome :-)
EDIT: Just discovered that the second case causes an infinite loop when using variables. Substitute it with:
case Sum(left,right) => Sum(simplify(left),simplify(right))
Unfortunately this breaks when left and right return Const, which could be simplified even further (e.g. Sum(Const(2),Const(3))).
Related
i have a question about the Parser in Scala. I'll just post the important part here so that there would not be too much codes. For the eval Function:
def eval(t: Term): Double = t match {
case Addition(l, r) => eval(l) + eval(r)
case Multiplication(l, r) => eval(l) * eval(r)
case Numeric(i) => i
case Variable("X") => 3
}
And the calculate function:
def calculate(arg: String): Double = {
return eval(parseAll(term, arg).get)
}
now i should overload the function "calculate" so that it takes an extra Parameter tup : (String, Double) and assign the value for this String. For example ("Y",2) then Y = 2 in the Parser. And then calculate the parser. But i don't know how to assign the value for this String. I had a stupid idea and tried this but it didn't work.
def calculate(arg: String, tup : (String, Double)) : Double = {
tup match {
case (a,b) => {
def eval(t : Term): Double = t match {
case Variable(a) => b
}
return eval(parseAll(term, arg).get)
}
}
can you guys pls help me out ? Thank you !!
You're almost there, you just need to tell the compiler that the a in your Variable pattern is actually the a from your (a, b) pattern. By default, what you do is called shadowing of the variable name a (in the scope of this pattern match, a is the value extracted in Variable, and the other a is forgotten).
What you want is something like
...
case Variable(`a`) => b
...
or, if your expression gets a little more complicated, you should rather use a guard:
...
case Variable(v) if v == a => b
...
EDIT However, now your eval function is not well defined. You need to put it all at once:
def eval(t: Term, varAssignement: (String, Double)): Double = t match {
case Addition(l, r) => eval(l) + eval(r)
case Multiplication(l, r) => eval(l) * eval(r)
case Numeric(i) => i
case Variable(a) if a == varAssignment._1 => varAssignment._2
}
Or, if you want to have multiple variables:
def eval(t: Term, assignments: Map[String, Double]): Double = t match {
case Addition(l, r) => eval(l) + eval(r)
case Multiplication(l, r) => eval(l) * eval(r)
case Numeric(i) => i
case Variable(a) if assignments.exists(a) => assignments(a)
}
Beware that you'll still get MatchErrors whenever an unassigned variable is used.
I've refactored my code for day 12 of advent of code by using monocle, a lens library in scala.
Is it possible to improve this code :
type Register = String
type Mem = Map[String, Int]
#Lenses
case class State(mem: Mem, pointer: Int)
def processInstruction(instructions: Seq[Instruction]): State => State = { s =>
(instructions(s.pointer) match {
case Inc(r) =>
State.pointer.modify( _ + 1) andThen (State.mem composeLens at(r)).modify(_.map(_ + 1))
case Dec(r) =>
State.pointer.modify( _ + 1) andThen (State.mem composeLens at(r)).modify(_.map(_ - 1))
case CpyInt(v, to) =>
State.pointer.modify( _ + 1) andThen (State.mem composeLens at(to)).set(Some(v))
case CpyReg(from, to) =>
State.pointer.modify( _ + 1) andThen (State.mem composeLens at(to)).set(Some(s.mem(from)))
case Jnz(r, v) => if (r != "1" && s.mem(r) == 0)
State.pointer.modify( _ + 1)
else
State.pointer.modify( _ + v )
}).apply(s)
}
And here is another try, separating the modification of each field
def processInstruction2(instructions: Seq[Instruction]): State => State = { s =>
val ptr = instructions(s.pointer) match {
case Jnz(r, v) if !(r != "1" && s.mem(r) == 0) => State.pointer.modify(_ + v)
case _ => State.pointer.modify(_ + 1)
}
val mem = instructions(s.pointer) match {
case Inc(r) => (State.mem composeLens at(r)).modify(_.map(_ + 1))
case Dec(r) => (State.mem composeLens at(r)).modify(_.map(_ - 1))
case CpyInt(v, to) => (State.mem composeLens at(to)).set(Some(v))
case CpyReg(from, to) => (State.mem composeLens at(to)).set(Some(s.mem(from)))
case _ => identity[State]
}
(ptr andThen mem)(s)
}
One more question : is there a way to use Map.withDefaultValue with monocle ?
The full code is here : https://gist.github.com/YannMoisan/b8ba25afc041d88706545527d9ec1988
You might want to use the second approach, because it separates handling of two fields.
However, the functions shouldn't be interpreted in sequence (andThen), but rather they should be combined as PartialFunctions with orElse.
def processInstruction3(instructions: Seq[Instruction]): State => State = {
val ptr: PartialFunction[Instruction, State => State] = {
case Jnz(r, v) =>
State.pointer.modify(_ + v)
}
val incPointer: State => State = State.pointer.modify( _ + 1)
def reg(r: String): Lens[State, Option[Int]] = State.mem composeLens at(r)
val mem: PartialFunction[Instruction, State => State] = {
case Inc(r) => reg(r).modify(_.orElse(Option(0)).map(_ + 1))
case Dec(r) => reg(r).modify(_.orElse(Option(0)).map(_ - 1))
case CpyInt(v, to) => reg(to).set(Some(v))
case CpyReg(from, to) => s => reg(to).set(reg(from).get(s))(s)
}
val interpreter = ptr orElse (mem andThen (_ andThen incPointer))
s => instructions.foldLeft(s)((s, i) => interpreter(i)(s))
}
UPDATE (after the Yann Moisan comment)
The execution may not terminate in case of infinite loop in user's program. So instead of the foldLeft we need some recursive function that will extract the next instruction by pointer:
#tailrec
def loop(s: State): State = {
if(s.pointer>=instructions.length)
s
else {
val instruction = instructions(s.pointer)
val nextState = interpreter(instruction)(s)
loop(nextState)
}
}
loop _
(The last line of processInstruction3 should be replaced with the above code)
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).
There is a list with type List[Option[String]], it may contain Some or None
val list:List[Option[String]] = List(Some("aaa"), None, Some("bbb"))
list match {
case /*List with all Some*/ => println("all items are Some")
case /*List with all None*/ => println("all items are None")
case /*List with Some and None*/ => println("Contain both Some and None")
}
But I don't know how to write it. Is it possible to use pattern matching?
You can write custom extractors:
object AllSome {
def unapply[T](l: List[Option[T]]) = l.forall(_.isDefined)
}
object AllNone {
def unapply[T](l: List[Option[T]]) = l.forall(_ == None)
}
object Mixed {
def unapply[T](l: List[Option[T]]) = !AllNone.unapply(l) && !AllSome.unapply(l)
}
And use them like:
list match {
case AllSome() => ???
case AllNone() => ???
case Mixed() => ???
}
One approach involves flattening the list and comparing the resulting length with the original length, like this,
list.flatten.length match {
case 0 => println("All items are None")
case len if len < l.length => println("Contain both Some and None")
case _ => println("All items are Some")
}
Update
To get the contents of each Some, simply list.flatten , namely for instance,
list.flatten
res: List(aaa, bbb)
and
List().flatten
res: List[Nothing] = List()
If you really want a solution with well-defined semantics and based on pattern matching you could do something as follows:
abstract class CollectionStatus
case object Empty extends CollectionStatus
case object AllSome extends CollectionStatus
case object AllNone extends CollectionStatus
case object Mixed extends CollectionStatus
object CollectionStatus {
def default: CollectionStatus = Empty
}
def folder(status: CollectionStatus, o: Option[_]): CollectionStatus = {
(status, o) match {
case (Empty, Some(_)) => AllSome
case (Empty, None) => AllNone
case (AllSome, Some(_)) => AllSome
case (AllNone, None) => AllNone
case _ => Mixed
}
}
Here's how I would use it:
List[Option[String]]().foldLeft(CollectionStatus.default)(folder _) //Empty
List(Option("foo"), Option("bar")).foldLeft(CollectionStatus.default)(folder _) //AllSome
List(Option("foo"), None).foldLeft(CollectionStatus.default)(folder _) //Mixed
List(None, None).foldLeft(CollectionStatus.default)(folder _) //AllNone
This could be further improved by replacing foldLeft with a tail recursive function that would accumulate the status of the list, and finish its computations without traversing the whole list if it recognized the list was "Mixed" already:
import scala.annotation.tailrec
def listStatus(list: List[Option[_]]): CollectionStatus = {
#tailrec
def inner(acc: CollectionStatus, ls: List[Option[_]]): CollectionStatus = {
acc match {
case Mixed => Mixed
case s => {
ls match {
case Nil => s
case h :: t => {
inner(folder(s, h), t)
}
}
}
}
}
inner(CollectionStatus.default, list)
}
val l: List[Option[String]] = List(Some("aaa"), None, Some("bbb"))
l.groupBy({
case Some(_) => "s"
case None => "n"
}).toList match {
case List(_,_) => println("both")
case List(a) => if( a._1 == "n") println("none") else println("some")
}
I have the following ADT for Formulas. (shortened to the important ones)
sealed trait Formula
case class Variable(id: String) extends Formula
case class Negation(f: Formula) extends Formula
abstract class BinaryConnective(val f0: Formula, val f1: Formula) extends Formula
Note that the following methods are defined in an implicit class for formulas.
Let's say i want to get all variables from a formula.
My first approach was:
Solution 1
def variables: Set[Variable] = formula match {
case v: Variable => HashSet(v)
case Negation(f) => f.variables
case BinaryConnective(f0, f1) => f0.variables ++ f1.variables
case _ => HashSet.empty
}
This approach is very simple to understand, but not tailrecursive. So I wanted to try something different. I implemented a foreach on my tree-like formulas.
Solution 2
def foreach(func: Formula => Unit) = {
#tailrec
def foreach(list: List[Formula]): Unit = list match {
case Nil =>
case _ => foreach(list.foldLeft(List.empty[Formula])((next, formula) => {
func(formula)
formula match {
case Negation(f) => f :: next
case BinaryConnective(f0, f1) => f0 :: f1 :: next
case _ => next
}
}))
}
foreach(List(formula))
}
Now I can implement many methods with the help of the foreach.
def variables2 = {
val builder = Set.newBuilder[Variable]
formula.foreach {
case v: Variable => builder += v
case _ =>
}
builder.result
}
Now finally to the question. Which solution is preferable in terms of efficieny? At least I find my simple first solution more aesthetic.
I would expect Solution 2 to be more efficient, because you aren't create many different HashSet instances and combining them together. It is also more general.
You can simplify your Solution 2, removing the foldLeft:
def foreach(func: Formula => Unit) = {
#tailrec
def foreach(list: List[Formula]): Unit = list match {
case Nil =>
case formula :: next => {
func(formula)
foreach {
formula match {
case Negation(f) => f :: next
case BinaryConnective(f0, f1) => f0 :: f1 :: next
case _ => next
}
}
}
}
foreach(List(formula))
}