Interpreters for the Free Monad - scala

I've been doing an exercise to try to implement a basic Calculator with Free Monad.
As I understand the intention of the Free Monad and what I wanted to achieve is:
write my program (math expression) once run it with different interpreters.
Now i am not sure that I did the 100% idiomatic implementation at least because:
My program kinda needs to be parametrized on the generic type A which should match the interpreter context.
def program[A] = for {
two <- lit[A](2)
four <- lit[A](4)
sum <- add(two, four)
} yield sum
program[Int].foldMap(eval) shouldBe 6
program[String].foldMap(print) shouldBe "(2 + 4)"
import cats.instances.option._
program[Option[Int]].foldMap(evalOpt) shouldBe Option(6)
The ADT/algebra and 'smart constructors'
trait Expression2[A] extends Product with Serializable
case class Lit[A](a: Int) extends Expression2[A]
case class Add[A](a: A, b: A) extends Expression2[A]
case class Mult[A](a: A, b: A) extends Expression2[A]
type ExprAlg[B] = Free[Expression2, B]
def lit[A](a: Int): ExprAlg[A] = Free.liftF(Lit(a))
def add[A](a: A, b: A): ExprAlg[A] = Free.liftF(Add(a, b))
def mult[A](a: A, b: A): ExprAlg[A] = Free.liftF(Mult(a, b))
The math interpreter:
def eval: Expression2 ~> Id = new (Expression2 ~> Id) {
override def apply[A](fa: Expression2[A]): Id[A] = eval(fa).asInstanceOf[A]
def eval[A](expression2: Expression2[A]): Int = expression2 match {
case Lit(n) => n
case Add(a, b) => a.asInstanceOf[Int] + b.asInstanceOf[Int]
case Mult(a, b) => a.asInstanceOf[Int] * b.asInstanceOf[Int]
}
}
The print interpreter:
def print: Expression2 ~> Id = new (Expression2 ~> Id) {
override def apply[A](fa: Expression2[A]): Id[A] = eval(fa).asInstanceOf[A]
def eval[A](expression2: Expression2[A]): String = expression2 match {
case Lit(n) => n.toString
case Add(a, b) => "(" + a.toString + " + " + b.toString + ")"
case Mult(a, b) => "(" + a.toString + " * " + b.toString + ")"
}
}
The math in Option interpreter:
def evalOpt: Expression2 ~> Option = new (Expression2 ~> Option) {
override def apply[A](fa: Expression2[A]): Option[A] = eval(fa).map{_.asInstanceOf[A]}
def eval[A](expression2: Expression2[A]): Option[Int] = expression2 match {
case Lit(n) => Option(n)
case Add(a, b) => Option(a.asInstanceOf[Int] + b.asInstanceOf[Int])
case Mult(a, b) => Option(a.asInstanceOf[Int] * b.asInstanceOf[Int])
}
}
Related to the Option interpreter, I would have expected that the a and b vars to be option, and in the string interpreter a and b to be strings because of my the ADT result type is A: Expression2[A].
I also tried instead of Lit[A](a: Int), to have Lit[A](a: A) but then it breaks down: i cannot pass different interpreters for the same expression when A is fixed to an Int in my program and I expect not to have to rewrite my program for different interpreters.

So a couple things. Generally you reaaaally want to avoid asInstanceOf because right now you can construct an Expression2 with any type and then it'd just crash on evaluating because it's not actually an Int. There's a couple ways to mitigate this. You can either just fix the type of the contained numeric type in your Expression2
import scalaz._
import Scalaz._
trait Expression2[A] extends Product with Serializable
case class Lit[A](a: Int) extends Expression2[Int]
case class Add[A](a: Int, b: Int) extends Expression2[Int]
case class Mult[A](a: Int, b: Int) extends Expression2[Int]
type ExprAlg[A] = Free[Expression2, A]
def lit(a: Int): ExprAlg[Int] = Free.liftF(Lit(a))
def add(a: Int, b: Int): ExprAlg[Int] = Free.liftF(Add(a, b))
def mult(a: Int, b: Int): ExprAlg[Int] = Free.liftF(Mult(a, b))
val eval: Expression2 ~> Id = new (Expression2 ~> Id) {
override def apply[A](fa: Expression2[A]): Id[A] = eval(fa)
def eval[A](expression2: Expression2[A]): A = expression2 match {
case Lit(n) => n
case Add(a, b) => a+b
case Mult(a, b) => a*b
}
}
Or you can associate the capability with the operations like this. basically you can think of the cases in your ADT like Add like this: The parameters of the case class are like function parameters and the type you put into the Extends is the result type.
import scalaz._
import Scalaz._
import spire.algebra._
import spire.implicits._
trait Expression2[A] extends Product with Serializable
case class Lit[A](a: A) extends Expression2[A]
case class Add[A](a: A, b: A)(implicit val ev:Semiring[A]) extends Expression2[A]
case class Mult[A](a: A, b: A)(implicit val ev:Semiring[A]) extends Expression2[A]
type ExprAlg[A] = Free[Expression2, A]
def lit[A](a: A): ExprAlg[A] = Free.liftF(Lit(a))
def add[A](a: A, b: A)(implicit ev:Semiring[A]): ExprAlg[A] = Free.liftF(Add(a, b))
def mult[A](a: A, b: A)(implicit ev:Semiring[A]): ExprAlg[A] = Free.liftF(Mult(a, b))
val eval: Expression2 ~> Id = new (Expression2 ~> Id) {
override def apply[A](fa: Expression2[A]): Id[A] = eval(fa)
def eval[A](expression2: Expression2[A]): Id[A] = expression2 match {
case Lit(n) => n
case x:Add[A] => x.ev.plus(x.a,x.b)
case x:Mult[A] => x.ev.times(x.a,x.b)
}
}
def program[A: Semiring](a:A,b:A) = for {
two <- lit(a)
four <- lit(b)
sum <- add(two, four)
} yield sum
println(program[Int](2,4).foldMap(eval) )
Now as for your Option case I am not quite sure why you want to interpret into an Option here. if you can do F ~> Id for some F, F ~> Option really is just Some applied to the first natural transformation.

Related

How monoids generalize over types

I was playing with cats' Monoids in scala when I see that the monoid operations are extended for Tuples in a natural way:
import cats.Monoid
object mon {
implicit object IntMonoid extends Monoid[Int] {
def combine(a: Int, b: Int) = a*a + b*b
def empty = 0
}
implicit object ListMonoid extends Monoid[List[Int]] {
def combine(a: List[Int], b: List[Int]): List[Int] =
a.zip(b).map(z => z._1 * z._2)
def empty = List(1)
}
def comb[T](a: T, b: T)(implicit m: Monoid[T]) =
m.combine(a, b)
}
val list1 = List(1, 2, 3)
val list2 = List(2, 3, 4)
println(mon.comb(list1, list2)) // outputs: List(2, 6, 12) as expected
val int1 = 2
val int2 = 4
println(mon.comb(int1, int2)) // outputs: 20 as expected
val x = (list1, int1)
val y = (list2, int2)
println(mon.comb(x, y)) // outputs: (List(2, 6, 12),20)
The last output is expected in a 'natural' way, but how does de compiler knows how to do it?
I've been trying to look for it in Cats' source code, but I'm not as experienced in Scala as to be able to know what to look for. I suppose the same methods holds for similar constructions like semigroups.
Your question boils down to how implicit derivation of typeclasses for generic types work; so let's see two examples:
A case where we want to provide an instance no matter what the generic is:
// Similar to the code you had, but without being tied to just List[Int],
// Since in this case the Int part is irrelevant.
implicit def monoidList[A]: Monoid[List[A]] =
new Monoid[List[A]] {
override final val empty: List[A] = Nil
override final def combine(l1: List[A], l2: List[A]): List[A] =
l1 ::: l2
}
A case where we require a proof of the generic type to provide the instance of the complex type:
implicit def optionMonoid[A](implicit aMonoid: Monoid[A]): Monoid[Option[A]] =
new Monoid[Option[A]] {
override final val empty: Option[A] = None
override final def combine(o1: Option[A], o2: Option[A]): Option[A] =
(o1, o2) match {
case (None, None) => None
case (Some(a), None) => Some(a)
case (None, Some(a)) => Some(a)
case (Some(a1), Some(a1)) => Some(aMonoid.combine(a1, a2))
}
}
Thus, you can now imagine how the Monoid[Tuple2[A, B]] of cats works, but just for completeness the code would be like this:
implicit def tuple2Monoid[A, B](implicit aMonoid: Monoid[A], bMonoid: Monoid[B]): Monoid[(A, B)] =
new Monoid[(A, B)] {
override final def empty: (A, B) =
(aMonoid.empty, bMonoid.empty)
override final def combine(t1: (A, B), t2: (A, B)): (A, B) =
(t1, t2) match {
case ((a1, b1), (a2, b2)) => (aMonoid.combine(a1, a2), bMonoid.combine(b1, b2))
}
}

Scala predicate composition

The java Predicate interface provides an or method that is used to combine multiple predicates. Example:
Predicate<Integer> p1;
Predicate<Integer> p2;
Predicate<Integer> p2 = p1.or(p2)
Since scala does not have the Predicate interface but uses Function1[A, Boolean] for this purpose what would be the best way to write this? Preferably without the use of external libraries.
I try to avoid the following:
val p1: (A => Boolean)
val p2: (A => Boolean)
val p3: (A => Boolean) = (a => p1(a) || p2(a))
You could provide the Predicate functionality in an implicit value class as
implicit class Predicate[A](val p1: A => Boolean) extends AnyVal {
def or[B >: A](p2: B => Boolean) = (a: A) => p1(a) || p2(a)
}
and then do
val gtOne = (x: Int) => x > 1
val ltMinusOne = (x: Int) => x < -1
val absGtOne = gtOne or ltMinusOne
absGtOne(-2) // true
absGtOne(0) // false
absGtOne(2) // true
You could provide an implicit conversion from A ⇒ Boolean to Predicate which supports the operations you want. Something like this:
implicit class Predicate[A](val p: A ⇒ Boolean) extends AnyVal {
type Predicate[A] = A ⇒ Boolean
def unary_! = (a: A) ⇒ !p(a)
def ==[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) == x(a)
def !=[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) != x(a)
def ||[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) || x(a)
def &&[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) && x(a)
def ^[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) ^ x(a)
def |[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) | x(a)
def &[B >: A](x: Predicate[B]) = (a: A) ⇒ p(a) & x(a)
}
This implements all the methods available in Boolean with the same semantics, e.g. Predicate.&& will only evaluate the second predicate if the first evaluates to true, whereas Predicate.| will always evaluate both predicates.
It's not part of the standard library, but if you only need simple expressions, you could:
Use the Java version, possibly using extension methods for syntactic sugar like p1 || p2 instead of p1.or(p2).
Roll your own case class Predicate[-A](p: A => Boolean) with a few simple methods like:
def ||[B <: A](other: Predicate[B]): Predicate[B] = ???
My stateful predicate:
/**
* Predicate logic with the state to print the function in natural language
*/
object StatefulPredicate {
class Predicate[E, T](predicate: E => T => Boolean, e: E, chain: Option[(Operator, Predicate[E, T])] = None) {
def test(t: T): Boolean = chain.map(c => c._1.execute(t, c._2.test(t), predicate(e))).getOrElse(predicate(e)(t))
def and(e: E): Predicate[E, T] = new Predicate[E, T](this.predicate, e, Some(AND, this))
def or(e: E): Predicate[E, T] = new Predicate[E, T](this.predicate, e, Some(OR, this))
override def toString: String = chain.map(c => c._2.toString + " " + c._1.toString + " " + e.toString).getOrElse(e.toString)
}
sealed trait Operator {
def execute[T](t: T, op1: Boolean, op2: T => Boolean): Boolean
}
case object AND extends Operator {
override def execute[T](t: T, op1: Boolean, op2: T => Boolean): Boolean = op1 && op2(t)
override def toString: String = "and"
}
case object OR extends Operator {
override def execute[T](t: T, op1: Boolean, op2: T => Boolean): Boolean = op1 || op2(t)
override def toString: String = "or"
}
def main(args: Array[String]): Unit = {
val p1: Predicate[Int, Seq[Int]] = new Predicate(e => s => s.contains(e), 10)
val p2: Predicate[Int, Seq[Int]] = p1.or(25)
val p3: Predicate[Int, Seq[Int]] = p2.and(25)
val p4: Predicate[Int, Seq[Int]] = p3.and(40)
print(p4.test(Seq[Int](10, 20, 30, 40)))
}
}

How to use cats and State Monad

I've used cats for the first time to solve day 1 of advent of code and I'm wondering if it's possible to improve things.
Given a method update with the following signature
def update(i: Instruction): PosAndDir => PosAndDir
I've come up with :
val state: State[PosAndDir, List[Unit]] = instructions.map(i => State.modify(update(i))).toList.sequenceU
val finalState = state.runS(PosAndDir(Pos(0, 0), North)).value
And also
def update2(i: Instruction): State[PosAndDir, Option[Pos]] =
State.modify(update(i)).inspect(pad => if (i == Walk) Some(pad.pos) else None)
…
val state = instructions.map(update2).toList.sequenceU
val positions = state.runA(PosAndDir(Pos(0, 0), North)).value.flatten
More precisely, questions are :
why do we need to call .value (with scalaz, it's transparent) ?
is there a way to write update2 with a for comprehension to improve readability ?
is there an Applicative instance for Seq in cats (I know there is not in scalaz). ?
any idea to improve the code ?
cats defines State[S, A] as an alias for stack-safe StateT[Eval, S , A] which is StateT[Trampoline, S, A] in scalaz terms, so runS returns Eval[A], where value will be run without stackoverflow even for very long flatMap sequences.
Using some more additional imports
import cats.data.{State, StateT}
import cats.MonadState
import cats.syntax.functorFilter._
import cats.instances.option._
and some preparations
type Walk[x] = StateT[Option, PosAndDir, x]
val stateMonad = MonadState[Walk, PosAndDir]
import stateMonad._
you can make your function look like this
def update2(i: Instruction): StateT[Option, PosAndDir, Pos] =
for (pad ← get if i == Walk) yield pad.pos
not that this solution will not work in 2.12 due to this improvement, you can make it work with this workaround
implicit class FunctorWithFilter[F[_] : FunctorFilter, A](fa: F[A]) {
def withFilter(f: A ⇒ Boolean) = fa.filter(f)
}
There is no instances for Seq, this answer describes why. While there are some non-orthodox instances in the alleycats project. I'm not really sure if you need for Applicative[Seq], from your code you are rather have need for Traverse[Seq], or if you replace your sequence with sequence_ even Foldable[Seq].
Good news there is Foldable[Iterable] in the alleycats, and here is my attempt to define something lookalike for Seq instance
implicit val seqInstance = new MonadFilter[Seq] with Traverse[Seq] {
def traverse[G[_] : Applicative, A, B](fa: Seq[A])(f: (A) ⇒ G[B]): G[Seq[B]] =
fa match {
case head +: tail ⇒ f(head).map2(traverse(tail)(f))(_ +: _)
case _empty ⇒ Seq.empty[B].pure[G]
}
def foldLeft[A, B](fa: Seq[A], b: B)(f: (B, A) ⇒ B): B = fa.foldLeft(b)(f)
def foldRight[A, B](fa: Seq[A], lb: Eval[B])(f: (A, Eval[B]) ⇒ Eval[B]): Eval[B] =
fa match {
case head +: tail ⇒ f(head, foldRight(tail, lb)(f))
case _empty ⇒ lb
}
def pure[A](x: A): Seq[A] = Seq(x)
def empty[A]: Seq[A] = Seq.empty[A]
def flatMap[A, B](fa: Seq[A])(f: (A) ⇒ Seq[B]): Seq[B] = fa.flatMap(f)
def tailRecM[A, B](a: A)(f: (A) ⇒ Seq[Either[A, B]]): Seq[B] = {
#tailrec def go(seq: Seq[Either[A, B]]): Seq[B] =
if (seq.contains((_: Either[A, B]).isLeft))
go(seq.flatMap {
case Left(a) ⇒ f(a)
case b ⇒ Seq(b)
}) else seq.collect { case Right(b) ⇒ b }
go(Seq(Left(a)))
}
override def mapFilter[A, B](fa: Seq[A])(f: (A) ⇒ Option[B]): Seq[B] =
fa.flatMap(f(_).toSeq)
}
didn't spent much time but here is my attempt to simplifying some parts via the Monocle library:
import cats.{MonadState, Foldable, Functor}
import cats.instances.option._
import cats.syntax.foldable._
import cats.syntax.functor._
import cats.syntax.functorFilter._
import monocle.macros.Lenses
#Lenses
case class Pos(x: Int, y: Int)
sealed abstract class Dir(val cmd: Pos ⇒ Pos)
case object South extends Dir(Pos.y.modify(_ - 1))
case object North extends Dir(Pos.y.modify(_ + 1))
case object East extends Dir(Pos.x.modify(_ + 1))
case object West extends Dir(Pos.x.modify(_ - 1))
#Lenses
case class PosAndDir(pos: Pos, dir: Dir)
val clockwise = Vector(North, East, South, West)
val right: Map[Dir, Dir] = clockwise.zip(clockwise.tail :+ clockwise.head).toMap
val left: Map[Dir, Dir] = right.map(_.swap)
sealed abstract class Instruction(val cmd: PosAndDir ⇒ PosAndDir)
case object TurnLeft extends Instruction(PosAndDir.dir.modify(left))
case object TurnRight extends Instruction(PosAndDir.dir.modify(right))
case object Walk extends Instruction(pd ⇒ PosAndDir.pos.modify(pd.dir.cmd)(pd))
def runInstructions[F[_] : Foldable : Functor](instructions: F[Instruction])(start: PosAndDir): PosAndDir =
instructions.map(i => State.modify(i.cmd)).sequence_.runS(start).value

Type class implementation for hierarchy

I am studying Scala and trying to implement some abstractions for custom types. Defining scalaz monoids for concrete classes is quite straightforward. But how to declare one Monoid for the type hierarchy? Assuming this code:
sealed trait Base
case class A(v:Int) extends Base
object N extends Base
object Main {
// Wanna one monoid for all the Base's
implicit val baseMonoid = new Monoid[Base] {
override def append(f1: Base, f2: => Base): Base = f1 match {
case A(x) => f2 match {
case A(y) => A(x + y)
case N => A(x)
}
case N => f2
}
override def zero = N
}
def main(args: Array[String]): Unit = {
println(∅[Base] |+| A(3) |+| A(2)) // Compiles
println(A(3) |+| A(2)) // Not compiles
}
}
How to make state A() |+| B() workable in the example above?
This compiles:
import scalaz._, Scalaz._
sealed trait Base
case class A(a: Int) extends Base
case class B(b: Int) extends Base
object N extends Base
object BullShit {
// Wanna one monoid for all the Base's
implicit val sg: Semigroup[Base] = new Semigroup[Base] {
override def append(f1: Base, f2: => Base): Base = f1 match {
case A(a) => f2 match {
case A(a1) => A(a + a1)
case B(b) => A(a + b)
case N => N
}
case B(b) => f2 match {
case A(a) => B(a + b)
case B(b1) => B(b + b1)
case N => N
}
case N => f2
}
}
println((A(1): Base) |+| (B(2): Base))
}
And your example would compile if you tell Scala's horrible type inferencer what you mean:
sealed trait Base
case class A(v: Int) extends Base
object N extends Base
object Main {
// Wanna one monoid for all the Base's
implicit val baseMonoid = new Monoid[Base] {
override def append(f1: Base, f2: => Base): Base = f1 match {
case A(x) => f2 match {
case A(y) => A(x + y)
case N => A(x)
}
case N => f2
}
override def zero = N
}
def main(args: Array[String]): Unit = {
import scalaz._, Scalaz._
println(∅[Base] |+| A(3) |+| A(2)) // Compiles
println((A(3): Base) |+| (A(2): Base)) // now it compiles
}
}

How to define <*> for Option[List[_]] n Scala

This is a followup to my previous question with an example found on the Internet.
Suppose I define a typeclass Applicative as follows:
trait Functor[T[_]]{
def map[A,B](f:A=>B, ta:T[A]):T[B]
}
trait Applicative[T[_]] extends Functor[T] {
def unit[A](a:A):T[A]
def ap[A,B](tf:T[A=>B], ta:T[A]):T[B]
}
I can define an instance of Applicative for List
object AppList extends Applicative[List] {
def map[A,B](f:A=>B, as:List[A]) = as.map(f)
def unit[A](a: A) = List(a)
def ap[A,B](fs:List[A=>B], as:List[A]) = for(f <- fs; a <- as) yield f(a)
}
For convenience I can define an implicit conversion to add a method <*> to List[A=>B]
implicit def toApplicative[A, B](fs: List[A=>B]) = new {
def <*>(as: List[A]) = AppList.ap(fs, as)
}
Now I can do a cool thing !
zip two lists List[String] and apply f2 to every pair in applicative style
val f2: (String, String) => String = {(first, last) => s"$first $last"}
val firsts = List("a", "b", "c")
val lasts = List("x", "y", "z")
scala> AppList.unit(f2.curried) <*> firsts <*> lasts
res31: List[String] = List(a x, a y, a z, b x, b y, b z, c x, c y, c z)
So far, so good but now I have:
val firstsOpt = Some(firsts)
val lastsOpt = Some(lasts)
I would like to zip firsts and lasts, apply f2, and get Option[List[String]] in applicative style. In other words I need <*> for Option[List[_]]. How can I do it ?
Firstly, you need an instance of applicative for Option:
implicit object AppOption extends Applicative[Option] {
def map[A, B](f: A => B, o: Option[A]) = o.map(f)
def unit[A](a: A): Option[A] = Some(a)
def ap[A, B](of: Option[A => B], oa: Option[A]) = of match {
case Some(f) => oa.map(f)
case None => None
}
}
Then you can also create an applicative instance for the composition of two applicatives (note, based on the Haskell version):
class AppComp[F[_], G[_]](fa: Applicative[F], ga: Applicative[G]) extends Applicative[({ type f[A] = F[G[A]]})#f] {
def map[A, B](f: A => B, a: F[G[A]]): F[G[B]] = fa.map((g: G[A]) => ga.map(f, g), a)
def unit[A](a: A) = fa.unit(ga.unit(a))
def ap[A, B](f: F[G[A => B]], a: F[G[A]]): F[G[B]] = {
val liftg: G[A => B] => (G[A] => G[B]) = gf => (gx => ga.ap(gf, gx))
val ffg: F[G[A] => G[B]] = fa.map(liftg, f)
fa.ap(ffg, a)
}
}
implicit def toComp[F[_], G[_]](implicit fa: Applicative[F], ga: Applicative[G]) = new AppComp[F, G](fa, ga)
Finally you can now do:
val ola = toComp[Option, List]
ola.ap(ola.ap(ola.unit(f2.curried), firstsOpt), lastsOpt)
You could probably also remove some of the noise by generalising <*> to work for any applicative.