Double) extends Expr { override def eval = value } case class Add(a: Expr, b: Expr) extends Expr { override def eval = ??? } trait Expr case class Number(value: Double) extends Expr case class Add(a: Expr, b: Expr) extends Expr FP OOP INITIAL def evaluate(e: Expr): Double = e match { case Number(a) => a case Add(a, b) => ??? }
= e match { case Number(a) => a case Add(a, b) => evaluate(a) + evaluate(b) case Neg(a) => - evaluate(a) } def print(e: Expr): String = e match { case Number(a) => a.toString case Add(a, b) => s"(${print(a)} + ${print(b)})" case Neg(a) => s"-${print(a)}" } case class Neg(a: Expr) extends Expr { override def eval = - a.eval override def print = s"-${a.print}" } FP OOP FORM
science, a type class is a type system construct that supports ad hoc polymorphism. This is achieved by adding constraints to type variables in parametrically polymorphic types. Such a constraint typically involves a type class T and a type variable A, and means that [A] can only be instantiated to a type whose members support the overloaded operations associated with [T].”
Boolean SCALA HASKELL trait Eq[A] { def areEquals(a: A, b: A): Boolean } implicit val moduloEq: Eq[Int] = new Eq[Int] { def areEquals(a: Int, b: Int) = a % 5 == b % 5 } instance Eq Int where areEquals a b = a % 5 == b % 5
(a, a) pairEquals a b = if a `areEquals` b then Just (a, b) else Nothing SCALA HASKELL def pairEquals[A](a: A, b: A)(implicit eq: Eq[A]) = { if(eq.areEquals(a, b)) Some((a, b)) else None } trait Eq[A] { def areEquals(a: A, b: A): Boolean } implicit val moduloEq: Eq[Int] = new Eq[Int] { def areEquals(a: Int, b: Int) = a % 5 == b % 5 } instance Eq Int where areEquals a b = a % 5 == b % 5 class Eq a where areEquals :: a -> a -> Boolean
b: A): Boolean } SIMULACRUM def pairEquals[A: Eq](a: A, b: A): Option[(A, A)] = { if(a === b) Some((a, b)) else None } HASKELL pairEquals :: (Eq a) => a -> a -> Maybe (a, a) pairEquals a b = if a `areEquals` b then Just (a, b) else Nothing instance Eq Int where areEquals a b = a % 5 == b % 5 class Eq a where areEquals :: a -> a -> Boolean
case class Add[A <: Expression, B <: Expression](a: A, b: B) extends Expression @typeclass trait Eval[A <: Expression] { def eval(expression: A): Double }