sealed trait Listcase class Cons( head: Int, tail: List) extends Listcase object Nil extends List
sealed trait Listcase class Cons( head: Int, tail: List) extends Listcase object Nil extends List
sealed trait Listcase class Cons( head: Int, tail: List) extends Listcase object Nil extends List
sealed trait Listcase class Cons( head: Int, tail: List) extends Listcase object Nil extends List
sealed trait Listcase class Cons( head: Int, tail: List) extends Listcase object Nil extends List
sealed trait Listcase class Cons( head: Int, tail: List) extends Listcase object Nil extends List
sealed trait Listcase class Cons( head: Int, tail: List) extends Listcase object Nil extends List
val ints: List = Cons(3, Cons(2, Cons(1, Nil)))
val ints: List = Cons(3, Cons(2, Cons(1, Nil)))
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * 2 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * 2 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * 2 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * 2 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * 2 * 1 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * 2 * 1 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * 2 * 1 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * 2 * 1 * ???
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * 2 * 1 * 1
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints) = 3 * 2 * 1 * 1
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints)// res0: Int = 6
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints)
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints)
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints)
def product( values: List): Int = values match { case Cons(head, tail) => head * product(tail) case Nil => 1 }
product(ints)
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
mkString(ints)// res1: String = 3 :: 2 :: 1 :: nil
Structural recursion works by:
Structural recursion works by:
Structural recursion works by:
providing a solution to the smallest problem.
for larger problems: relying on the solution to smaller problems.
Structural recursion works by:
providing a solution to the smallest problem.
for larger problems: relying on the solution to smaller problems.
if this makes you think of proof by induction, well done.
mkString
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
mkString
def mkString( values: List): String = values match { case Cons(head, tail) => head + " :: " + mkString(tail) case Nil => "nil" }
mkString
def recurse( values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(tail) case Nil => "nil" }
mkString
def recurse( values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(tail) case Nil => "nil" }
recurse(ints)// res2: String = 3 :: 2 :: 1 :: nil
mkString
mkString
mkString
mkString
mkString
mkString
mkString
mkString
def recurse( values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(tail) case Nil => "nil" }
def recurse( values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(tail) case Nil => "nil" }
val base = "nil"
def recurse( values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(tail) case Nil => "nil" }
val base = "nil"
def recurse( values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(tail) case Nil => base }
val base = "nil"
def recurse( base : String, values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(tail) case Nil => base }
def recurse( base : String, values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(base, tail) case Nil => base }
def recurse( base : String, values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(base, tail) case Nil => base }
recurse(base, ints)// res3: String = 3 :: 2 :: 1 :: nil
def recurse( base : String, values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(base, tail) case Nil => base }
def recurse( base : String, values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(base, tail) case Nil => base }
def recurse( base : String, values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(base, tail) case Nil => base }
def recurse( base : String, values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(base, tail) case Nil => base }
def step(head: Int, tailResult: String) = head + " :: " + tailResult
def recurse( base : String, values: List): String = values match { case Cons(head, tail) => head + " :: " + recurse(base, tail) case Nil => base }
def step(head: Int, tailResult: String) = head + " :: " + tailResult
def recurse( base : String, values: List): String = values match { case Cons(head, tail) => step(head, recurse(base, tail)) case Nil => base }
def step(head: Int, tailResult: String) = head + " :: " + tailResult
def recurse( base : String, step : (Int, String) => String, values: List): String = values match { case Cons(head, tail) => step(head, recurse(base, tail)) case Nil => base }
def recurse( base : String, step : (Int, String) => String, values: List): String = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
def recurse( base : String, step : (Int, String) => String, values: List): String = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
recurse(base, step, ints)// res4: String = 3 :: 2 :: 1 :: nil
def recurse( base : String, step : (Int, String) => String, values: List): String = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
def recurse[A]( base : String, step : (Int, String) => String, values: List): String = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
def recurse[A]( base : String, step : (Int, String) => String, values: List): String = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
recurse(base, step, ints)// res5: String = 3 :: 2 :: 1 :: nil
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = values match { case Cons(head, tail) => step(head, recurse(base, step, tail)) case Nil => base }
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop(values)}
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop(values)}
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop(values)}
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop(values)}
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop(values)}
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop(values)}
recurse(base, step, ints)// res6: String = 3 :: 2 :: 1 :: nil
def recurse[A]( base : A, step : (Int, A) => A, values: List): A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop(values)}
def recurse[A]( base: A, step: (Int, A) => A): A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
def recurse[A]( base: A, step: (Int, A) => A): A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
def recurse[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
def recurse[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
recurse(base, step)(ints)// res7: String = 3 :: 2 :: 1 :: nil
def mkString(ints: List): String = recurse(base, step)(ints)
def mkString(ints: List): String = recurse(base, step)(ints)
def mkString: String = recurse(base, step)
def mkString: List => String = recurse(base, step)
def mkString: List => String = recurse(base, step)
val mkString: List => String = recurse(base, step)
val mkString: List => String = recurse(base, step)
mkString(ints)// res8: String = 3 :: 2 :: 1 :: nil
def recurse[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
fold(base, step)(ints)// res9: String = 3 :: 2 :: 1 :: nil
product
as a foldval product: List => Int = fold[Int]( base = 1, step = (head, tailProduct) => head * tailProduct )
product
as a foldval product: List => Int = fold[Int]( base = 1, step = (head, tailProduct) => head * tailProduct )
product
as a foldval product: List => Int = fold[Int]( base = 1, step = (head, tailProduct) => head * tailProduct )
product
as a foldval product: List => Int = fold[Int]( base = 1, step = (head, tailProduct) => head * tailProduct )
product
as a foldval product: List => Int = fold[Int]( base = 1, step = (head, tailProduct) => head * tailProduct )
product(ints)// res10: Int = 6
Structural recursion is generalised by:
Structural recursion is generalised by:
Structural recursion is generalised by:
parameterising the base case.
parameterising the step.
Structural recursion is generalised by:
parameterising the base case.
parameterising the step.
... knowing the structure of your type.
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
val project: List => Option[(Int, List)] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
val project: List => Option[(Int, List)] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
val project: List => Option[(Int, List)] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
val project: List => Option[(Int, List)] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
val project: List => Option[(Int, List)] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
val project: List => Option[(Int, List)] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = state match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = project(state) match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = project(state) match { case Cons(head, tail) => step(head, loop(tail)) case Nil => base } loop}
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => step(head, loop(tail)) case Nil => base } loop}
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => step(head, loop(tail)) case Nil => base } loop}
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => step(head, loop(tail)) case None => base } loop}
def fold[A]( base: A, step: (Int, A) => A): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => step(head, loop(tail)) case None => base } loop}
def fold[A]( base : A, step : (Int, A) => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => step(head, loop(tail)) case None => base } loop}
def fold[A]( base : A, step : (Int, A) => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => step(head, loop(tail)) case None => base } loop}
fold(base, step, project)(ints)// res11: String = 3 :: 2 :: 1 :: nil
base
and step
base
and step
def fold[A]( base : A, step : (Int, A) => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => step(head, loop(tail)) case None => base } loop}
base
and step
val op: Option[(Int, String)] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
base
and step
val op: Option[(Int, String)] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
base
and step
val op: Option[(Int, String)] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
base
and step
val op: Option[(Int, String)] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
base
and step
val op: Option[(Int, String)] => String = { case Some((head, tailResult)) => head + " :: " + tailResult case None => base}
base
and step
val op: Option[(Int, String)] => String = { case Some((head, tailResult)) => head + " :: " + tailResult case None => base}
base
and step
val op: Option[(Int, String)] => String = { case Some((head, tailResult)) => head + " :: " + tailResult case None => base}
base
and step
val op: Option[(Int, String)] => String = { case Some((head, tailResult)) => head + " :: " + tailResult case None => "nil"}
base
and step
val op: Option[(Int, String)] => String = { case Some((head, tailResult)) => head + " :: " + tailResult case None => "nil"}
base
and step
def fold[A]( base : A, step : (Int, A) => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => step(head, loop(tail)) case None => base } loop}
base
and step
def fold[A]( op : Option[(Int, A)] => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => step(head, loop(tail)) case None => base } loop}
base
and step
def fold[A]( op : Option[(Int, A)] => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => step(head, loop(tail)) case None => base } loop}
base
and step
def fold[A]( op : Option[(Int, A)] => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => op(Some((head, loop(tail)))) case None => base } loop}
base
and step
def fold[A]( op : Option[(Int, A)] => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => op(Some((head, loop(tail)))) case None => base } loop}
base
and step
def fold[A]( op : Option[(Int, A)] => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => op(Some((head, loop(tail)))) case None => op(None) } loop}
base
and step
def fold[A]( op : Option[(Int, A)] => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => op(Some((head, loop(tail)))) case None => op(None) } loop}
fold(op, project)(ints)// res12: String = 3 :: 2 :: 1 :: nil
base
and step
base
and step
base
and step
def fold[A]( op : Option[(Int, A)] => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = project(state) match { case Some((head, tail)) => op(Some((head, loop(tail)))) case None => op(None) } loop}
base
and step
def fold[A]( op : Option[(Int, A)] => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
base
and step
def fold[A]( op : Option[(Int, A)] => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
fold(op, project)(ints)// res13: String = 3 :: 2 :: 1 :: nil
base
and step
base
and step
base
and step
type ListF[A] = Option[(Int, A)]
type ListF[A] = Option[(Int, A)]
type ListF[A] = Option[(Int, A)]
type ListF[A] = Option[(Int, A)]
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
type ListF[A] = Option[(Int, A)]
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
type ListF[A] = Option[(Int, A)]
val op: ListF[String] => String = { case Some((head, tailResult)) => head + " :: " + tailResult case None => "nil"}
type ListF[A] = Option[(Int, A)]
val op: ListF[String] => String = { case Some((head, tailResult)) => head + " :: " + tailResult case None => "nil"}
def fold[A]( op : Option[(Int, A)] => A, project: List => Option[(Int, List)]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
fold(op, project)(ints)// res14: String = 3 :: 2 :: 1 :: nil
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(project(state) match { case Some((head, tail)) => Some((head, loop(tail))) case None => None }) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List]): ListF[A] = state match { case Some((head, tail)) => Some((head, loop(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List]): ListF[A] = state match { case Some((head, tail)) => Some((head, loop(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List]): ListF[A] = state match { case Some((head, tail)) => Some((head, loop(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List]): ListF[A] = state match { case Some((head, tail)) => Some((head, loop(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List]): ListF[A] = state match { case Some((head, tail)) => Some((head, loop(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List]): ListF[A] = state match { case Some((head, tail)) => Some((head, loop(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List]): ListF[A] = state match { case Some((head, tail)) => Some((head, loop(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List]): ListF[A] = state match { case Some((head, tail)) => Some((head, loop(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List], f: List => A): ListF[A] = state match { case Some((head, tail)) => Some((head, loop(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List], f: List => A): ListF[A] = state match { case Some((head, tail)) => Some((head, loop(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state))) def go(state: ListF[List], f: List => A): ListF[A] = state match { case Some((head, tail)) => Some((head, f(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state), loop)) def go(state: ListF[List], f: List => A): ListF[A] = state match { case Some((head, tail)) => Some((head, f(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state), loop)) def go(state: ListF[List], f: List => A): ListF[A] = state match { case Some((head, tail)) => Some((head, f(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state), loop)) def go(state: ListF[List], f: List => A): ListF[A] = state match { case Some((head, tail)) => Some((head, f(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state), loop)) def go(state: ListF[List], f: List => A): ListF[A] = state match { case Some((head, tail)) => Some((head, f(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state), loop)) def go(state: ListF[List], f: List => A): ListF[A] = state match { case Some((head, tail)) => Some((head, f(tail))) case None => None } loop}
trait Functor[F[_]] { def map[A, B](fa: F[A], f: A => B): F[B]}
trait Functor[F[_]] { def map[A, B](fa: F[A], f: A => B): F[B]}
trait Functor[F[_]] { def map[A, B](fa: F[A], f: A => B): F[B]}
trait Functor[F[_]] { def map[A, B](fa: F[A], f: A => B): F[B]}
trait Functor[F[_]] { def map[A, B](fa: F[A], f: A => B): F[B]}
trait Functor[F[_]] { def map[A, B](fa: F[A], f: A => B): F[B]}
trait Functor[F[_]] { def map[A, B](fa: F[A], f: A => B): F[B]}
implicit val listFFunctor = new Functor[ListF] { override def map[A, B](list: ListF[A], f: A => B) = list match { case Some((head, tail)) => Some((head, f(tail))) case None => None }}
implicit val listFFunctor = new Functor[ListF] { override def map[A, B](list: ListF[A], f: A => B) = list match { case Some((head, tail)) => Some((head, f(tail))) case None => None }}
implicit val listFFunctor = new Functor[ListF] { override def map[A, B](list: ListF[A], f: A => B) = list match { case Some((head, tail)) => Some((head, f(tail))) case None => None }}
implicit val listFFunctor = new Functor[ListF] { override def map[A, B](list: ListF[A], f: A => B) = list match { case Some((head, tail)) => Some((head, f(tail))) case None => None }}
implicit val listFFunctor = new Functor[ListF] { override def map[A, B](list: ListF[A], f: A => B) = list match { case Some((head, tail)) => Some((head, f(tail))) case None => None }}
implicit val listFFunctor = new Functor[ListF] { override def map[A, B](list: ListF[A], f: A => B) = list match { case Some((head, tail)) => Some((head, f(tail))) case None => None }}
implicit val listFFunctor = new Functor[ListF] { override def map[A, B](list: ListF[A], f: A => B) = list match { case Some((head, tail)) => Some((head, f(tail))) case None => None }}
def map[F[_], A, B]( fa : F[A], f : A => B)(implicit functor: Functor[F]): F[B] = functor.map(fa, f)
def map[F[_], A, B]( fa : F[A], f : A => B)(implicit functor: Functor[F]): F[B] = functor.map(fa, f)
def map[F[_], A, B]( fa : F[A], f : A => B)(implicit functor: Functor[F]): F[B] = functor.map(fa, f)
def map[F[_], A, B]( fa : F[A], f : A => B)(implicit functor: Functor[F]): F[B] = functor.map(fa, f)
def map[F[_], A, B]( fa : F[A], f : A => B)(implicit functor: Functor[F]): F[B] = functor.map(fa, f)
def map[F[_], A, B]( fa : F[A], f : A => B)(implicit functor: Functor[F]): F[B] = functor.map(fa, f)
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state), loop)) def go(state: ListF[List], f: List => A): ListF[A] = state match { case Some((head, tail)) => Some((head, f(tail))) case None => None } loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state), loop)) def go(state: ListF[List], f: List => A): ListF[A] = map(state, f) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(go(project(state), loop)) def go(state: ListF[List], f: List => A): ListF[A] = map(state, f) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) def go(state: ListF[List], f: List => A): ListF[A] = map(state, f) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) def go(state: ListF[List], f: List => A): ListF[A] = map(state, f) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) loop}
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) loop}
fold(op, project)(ints)// res15: String = 3 :: 2 :: 1 :: nil
ListF
ListF
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) loop}
ListF
def fold[A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) loop}
ListF
def fold[F[_]: Functor, A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) loop}
ListF
def fold[F[_]: Functor, A]( op : ListF[A] => A, project: List => ListF[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) loop}
ListF
def fold[F[_]: Functor, A]( op : F[A] => A, project: List => F[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) loop}
ListF
def fold[F[_]: Functor, A]( op : F[A] => A, project: List => F[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) loop}
fold(op, project).apply(ints)// res16: String = 3 :: 2 :: 1 :: nil
ListF
ListF
List
List
def fold[F[_]: Functor, A]( op : F[A] => A, project: List => F[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) loop}
List
def fold[F[_]: Functor, A, B]( op : F[A] => A, project: List => F[List]): List => A = { def loop(state: List): A = op(map(project(state), loop)) loop}
List
def fold[F[_]: Functor, A, B]( op : F[A] => A, project: List => F[List]): List => A = { def loop(stage: List): A = op(map(project(state), loop)) loop}
List
def fold[F[_]: Functor, A, B]( op : F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = op(map(project(state), loop)) loop}
List
def fold[F[_]: Functor, A, B]( op : F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = op(map(project(state), loop)) loop}
fold(op, project).apply(ints)// res17: String = 3 :: 2 :: 1 :: nil
List
List
List
def fold[F[_]: Functor, A, B]( op : F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = op(map(project(state), loop)) loop}
def cata[F[_]: Functor, A, B]( op : F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = op(map(project(state), loop)) loop}
def cata[F[_]: Functor, A, B]( op : F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = op(map(project(state), loop)) loop}
def cata[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
def cata[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
def cata[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
cata(op, project).apply(ints)// res18: String = 3 :: 2 :: 1 :: nil
product
as a cataval productAlgebra: ListF[Int] => Int = { case Some((head, tailProduct)) => head * tailProduct case None => 1}val product: List => Int = cata(productAlgebra, project)
product
as a cataval productAlgebra: ListF[Int] => Int = { case Some((head, tailProduct)) => head * tailProduct case None => 1}val product: List => Int = cata(productAlgebra, project)
product
as a cataval productAlgebra: ListF[Int] => Int = { case Some((head, tailProduct)) => head * tailProduct case None => 1}val product: List => Int = cata(productAlgebra, project)
product
as a cataval productAlgebra: ListF[Int] => Int = { case Some((head, tailProduct)) => head * tailProduct case None => 1}val product: List => Int = cata(productAlgebra, project)
product
as a cataval productAlgebra: ListF[Int] => Int = { case Some((head, tailProduct)) => head * tailProduct case None => 1}val product: List => Int = cata(productAlgebra, project)
product
as a cataval productAlgebra: ListF[Int] => Int = { case Some((head, tailProduct)) => head * tailProduct case None => 1}val product: List => Int = cata(productAlgebra, project)
product
as a cataval productAlgebra: ListF[Int] => Int = { case Some((head, tailProduct)) => head * tailProduct case None => 1}val product: List => Int = cata(productAlgebra, project)
product
as a cataval productAlgebra: ListF[Int] => Int = { case Some((head, tailProduct)) => head * tailProduct case None => 1}val product: List => Int = cata(productAlgebra, project)
product(ints)// res19: Int = 6
Catamorphisms are:
Catamorphisms are:
Catamorphisms are:
structural recursion for types that can be projected into pattern functors.
far less complicated than their names make them out to be.
Catamorphisms are:
structural recursion for types that can be projected into pattern functors.
far less complicated than their names make them out to be.
a simple refactoring away from the familiar fold
.
sealed trait Treecase class Node( left : Tree, value: Int, right: Tree) extends Treecase object Leaf extends Tree
sealed trait Treecase class Node( left : Tree, value: Int, right: Tree) extends Treecase object Leaf extends Tree
sealed trait Treecase class Node( left : Tree, value: Int, right: Tree) extends Treecase object Leaf extends Tree
sealed trait Treecase class Node( left : Tree, value: Int, right: Tree) extends Treecase object Leaf extends Tree
sealed trait Treecase class Node( left : Tree, value: Int, right: Tree) extends Treecase object Leaf extends Tree
sealed trait Treecase class Node( left : Tree, value: Int, right: Tree) extends Treecase object Leaf extends Tree
sealed trait Treecase class Node( left : Tree, value: Int, right: Tree) extends Treecase object Leaf extends Tree
sealed trait Treecase class Node( left : Tree, value: Int, right: Tree) extends Treecase object Leaf extends Tree
val intTree = Node( Node( Node(Leaf, 1, Leaf), 2, Node(Leaf, 3, Leaf) ), 4, Leaf )// intTree: Node = Node(Node(Node(Leaf,1,Leaf),2,Node(Leaf,3,Leaf)),4,Leaf)
val intTree = Node( Node( Node(Leaf, 1, Leaf), 2, Node(Leaf, 3, Leaf) ), 4, Leaf )
sealed trait Treecase class Node( left : Tree, value: Int, right: Tree) extends Treecase object Leaf extends Tree
sealed trait Treecase class Node( left : Tree, value: Int, right: Tree) extends Treecase object Leaf extends Tree
sealed trait TreeFcase class Node( left : Tree, value: Int, right: Tree) extends TreeFcase object Leaf extends TreeF
sealed trait TreeFcase class Node( left : Tree, value: Int, right: Tree) extends TreeFcase object Leaf extends TreeF
sealed trait TreeFcase class NodeF( left : Tree, value: Int, right: Tree) extends TreeFcase object Leaf extends TreeF
sealed trait TreeFcase class NodeF( left : Tree, value: Int, right: Tree) extends TreeFcase object Leaf extends TreeF
sealed trait TreeFcase class NodeF( left : Tree, value: Int, right: Tree) extends TreeFcase object LeafF extends TreeF
sealed trait TreeFcase class NodeF( left : Tree, value: Int, right: Tree) extends TreeFcase object LeafF extends TreeF
sealed trait TreeF[A]case class NodeF( left : Tree, value: Int, right: Tree) extends TreeFcase object LeafF extends TreeF
sealed trait TreeF[A]case class NodeF( left : Tree, value: Int, right: Tree) extends TreeFcase object LeafF extends TreeF
sealed trait TreeF[A]case class NodeF[A]( left : Tree, value: Int, right: Tree) extends TreeF[A]case object LeafF extends TreeF
sealed trait TreeF[A]case class NodeF[A]( left : Tree, value: Int, right: Tree) extends TreeF[A]case object LeafF extends TreeF
sealed trait TreeF[A]case class NodeF[A]( left : A, value: Int, right: A) extends TreeF[A]case object LeafF extends TreeF
sealed trait TreeF[A]case class NodeF[A]( left : A, value: Int, right: A) extends TreeF[A]case object LeafF extends TreeF
sealed trait TreeF[A]case class NodeF[A]( left : A, value: Int, right: A) extends TreeF[A]case object LeafF extends TreeF[???]
sealed trait TreeF[A]case class NodeF[A]( left : A, value: Int, right: A) extends TreeF[A]case object LeafF extends TreeF[Nothing]
sealed trait TreeF[A]case class NodeF[A]( left : A, value: Int, right: A) extends TreeF[A]case object LeafF extends TreeF[Nothing]
sealed trait TreeF[+A]case class NodeF[A]( left : A, value: Int, right: A) extends TreeF[A]case object LeafF extends TreeF[Nothing]
sealed trait TreeF[+A]case class NodeF[A]( left : A, value: Int, right: A) extends TreeF[A]case object LeafF extends TreeF[Nothing]
def projectTree: Tree => TreeF[Tree] = { case Node(l, v, r) => NodeF(l, v, r) case Leaf => LeafF}
def projectTree: Tree => TreeF[Tree] = { case Node(l, v, r) => NodeF(l, v, r) case Leaf => LeafF}
def projectTree: Tree => TreeF[Tree] = { case Node(l, v, r) => NodeF(l, v, r) case Leaf => LeafF}
def projectTree: Tree => TreeF[Tree] = { case Node(l, v, r) => NodeF(l, v, r) case Leaf => LeafF}
def projectTree: Tree => TreeF[Tree] = { case Node(l, v, r) => NodeF(l, v, r) case Leaf => LeafF}
def projectTree: Tree => TreeF[Tree] = { case Node(l, v, r) => NodeF(l, v, r) case Leaf => LeafF}
implicit val treeFFunctor = new Functor[TreeF] { override def map[A, B](tree: TreeF[A], f: A => B) = tree match { case NodeF(left, i, right) => NodeF(f(left), i, f(right)) case LeafF => LeafF }}
implicit val treeFFunctor = new Functor[TreeF] { override def map[A, B](tree: TreeF[A], f: A => B) = tree match { case NodeF(left, i, right) => NodeF(f(left), i, f(right)) case LeafF => LeafF }}
implicit val treeFFunctor = new Functor[TreeF] { override def map[A, B](tree: TreeF[A], f: A => B) = tree match { case NodeF(left, i, right) => NodeF(f(left), i, f(right)) case LeafF => LeafF }}
implicit val treeFFunctor = new Functor[TreeF] { override def map[A, B](tree: TreeF[A], f: A => B) = tree match { case NodeF(left, i, right) => NodeF(f(left), i, f(right)) case LeafF => LeafF }}
implicit val treeFFunctor = new Functor[TreeF] { override def map[A, B](tree: TreeF[A], f: A => B) = tree match { case NodeF(left, i, right) => NodeF(f(left), i, f(right)) case LeafF => LeafF }}
implicit val treeFFunctor = new Functor[TreeF] { override def map[A, B](tree: TreeF[A], f: A => B) = tree match { case NodeF(left, i, right) => NodeF(f(left), i, f(right)) case LeafF => LeafF }}
implicit val treeFFunctor = new Functor[TreeF] { override def map[A, B](tree: TreeF[A], f: A => B) = tree match { case NodeF(left, i, right) => NodeF(f(left), i, f(right)) case LeafF => LeafF }}
val heightAlgebra: TreeF[Int] => Int = { case NodeF(left, _, right) => 1 + math.max(left, right) case LeafF => 0}
val heightAlgebra: TreeF[Int] => Int = { case NodeF(left, _, right) => 1 + math.max(left, right) case LeafF => 0}
val heightAlgebra: TreeF[Int] => Int = { case NodeF(left, _, right) => 1 + math.max(left, right) case LeafF => 0}
val heightAlgebra: TreeF[Int] => Int = { case NodeF(left, _, right) => 1 + math.max(left, right) case LeafF => 0}
val heightAlgebra: TreeF[Int] => Int = { case NodeF(left, _, right) => 1 + math.max(left, right) case LeafF => 0}
val heightAlgebra: TreeF[Int] => Int = { case NodeF(left, _, right) => 1 + math.max(left, right) case LeafF => 0}
val height: Tree => Int = cata(heightAlgebra, projectTree)
val height: Tree => Int = cata(heightAlgebra, projectTree)
val height: Tree => Int = cata(heightAlgebra, projectTree)
height(intTree)// res20: Int = 3
cata
works just fine with Tree
.cata
works just fine with Tree
.
it involves a lot of busywork though...
List
in terms of ListF
type List2 = ListF[???]
List
in terms of ListF
type List2 = ListF[???]
List
in terms of ListF
type List2 = ListF[???]
List
in terms of ListF
type List2 = ListF[???]
List
in terms of ListF
type List2 = ListF[List2]
List
in terms of ListF
type List2 = ListF[List2]// type List2 = ListF[List2]// ^// On line 2: error: illegal cyclic reference involving type List2
List
in terms of ListF
case class List2(value: ListF[List2])
List
in terms of ListF
case class List2(value: ListF[List2])
List2
val ints2: List2 = ???: List2
List2
val ints2: List2 = ???: List2
List2
val ints2: List2 = List2(???: ListF[List2])
List2
val ints2: List2 = List2(???: ListF[List2])
List2
val ints2: List2 = List2(Some((3, ???: List2 )))
List2
val ints2: List2 = List2(Some((3, ???: List2 )))
List2
val ints2: List2 = List2(Some((3, ???: List2 )))
List2
val ints2: List2 = List2(Some((3, List2(???: ListF[List2]) )))
List2
val ints2: List2 = List2(Some((3, List2(???: ListF[List2]) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, ???: List2 ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, ???: List2 ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, ???: List2 ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(???: ListF[List2]) ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(???: ListF[List2]) ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(Some((1, ???: List2 ))) ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(Some((1, ???: List2 ))) ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(Some((1, ???: List2 ))) ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(Some((1, List2(???: ListF[List2]) ))) ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(Some((1, List2(???: ListF[List2]) ))) ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(Some((1, List2(None) ))) ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(Some((1, List2(None) ))) ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(Some((1, List2(None) ))) ))) )))
List2
val ints2: List2 = List2(Some((3, List2(Some((2, List2(Some((1, List2(None) ))) ))) )))
List2
case class Tree2(value: TreeF[Tree2])
List2
case class Tree2(value: TreeF[Tree2])
List2
case class Tree2(value: TreeF[Tree2])
List2
case class Tree2(value: TreeF[Tree2])
List2
case class List2(value: ListF[List2])
List2
case class List2(value: ListF[List2])
List2
case class List2[F[_]](value: ListF[List2])
List2
case class List2[F[_]](value: ListF[List2])
List2
case class List2[F[_]](value: F[List2])
List2
case class List2[F[_]](value: F[List2[???]])
List2
case class List2[F[_]](value: F[List2[???]])
List2
case class List2[F[_]](value: F[List2[F]])
List2
case class List2[F[_]](value: F[List2[F]])
case class List2[F[_]](value: F[List2[F]])
case class Fix[F[_]](value: F[Fix[F]])
case class Fix[F[_]](value: F[Fix[F]])
case class Fix[F[_]](value: F[Fix[F]])
f(x) = x
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = x
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = x
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = x
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = x
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = x
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = f(x)
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = f(x)
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = f(x)
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = f(x)
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = f(fix(f))
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = f(fix(f))
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = f(fix(f))
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = f(fix(f))
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = f(fix(f))
case class Fix[F[_]](value: F[Fix[F]])
f(x) = xfix(f) = xfix(f) = f(fix(f))
List
in terms of Fix
type FixedList = Fix[ListF]
List
in terms of Fix
type FixedList = Fix[ListF]
List
in terms of Fix
type FixedList = Fix[ListF]
List
in terms of Fix
val fixedInts: FixedList = Fix[ListF](Some((3, Fix[ListF](Some((2, Fix[ListF](Some((1, Fix[ListF](None) ))) ))) )))
List
in terms of Fix
val fixedInts: FixedList = Fix[ListF](Some((3, Fix[ListF](Some((2, Fix[ListF](Some((1, Fix[ListF](None) ))) ))) )))
List
in terms of Fix
val fixedInts: FixedList = Fix[ListF](Some((3, Fix[ListF](Some((2, Fix[ListF](Some((1, Fix[ListF](None) ))) ))) )))
Tree
in terms of TreeF
type FixedTree = Fix[TreeF]
Tree
in terms of TreeF
type FixedTree = Fix[TreeF]
Tree
in terms of TreeF
type FixedTree = Fix[TreeF]
Tree
in terms of TreeF
val fixedIntTree: FixedTree = Fix[TreeF](NodeF( Fix[TreeF](NodeF( Fix[TreeF](NodeF(Fix[TreeF](LeafF), 1, Fix[TreeF](LeafF))), 2, Fix[TreeF](NodeF(Fix[TreeF](LeafF), 3, Fix[TreeF](LeafF))) )), 4, Fix[TreeF](LeafF) ))
Tree
in terms of TreeF
val fixedIntTree: FixedTree = Fix[TreeF](NodeF( Fix[TreeF](NodeF( Fix[TreeF](NodeF(Fix[TreeF](LeafF), 1, Fix[TreeF](LeafF))), 2, Fix[TreeF](NodeF(Fix[TreeF](LeafF), 3, Fix[TreeF](LeafF))) )), 4, Fix[TreeF](LeafF) ))
cata
with Fix
def cata[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
cata
with Fix
def cata[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
cata
with Fix
def cataFix[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
cata
with Fix
def cataFix[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
cata
with Fix
cata
with Fix
cata
with Fix
def cataFix[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
cata
with Fix
def cataFix[F[_]: Functor, A]( algebra: F[A] => A, project: Fix[F] => F[Fix[F]]): Fix[F] => A = { def loop(state: Fix[F]): A = algebra(map(project(state), loop)) loop}
cata
with Fix
def cataFix[F[_]: Functor, A]( algebra: F[A] => A, project: Fix[F] => F[Fix[F]]): Fix[F] => A = { def loop(state: Fix[F]): A = algebra(map(project(state), loop)) loop}
cata
with Fix
cata
with Fix
Fix
Fix
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
Fix
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
Fix
val projectFix: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
Fix
val projectFix: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
Fix
val projectFix: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
Fix
val projectFix: FixedList => ListF[FixedList] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
Fix
val projectFix: FixedList => ListF[FixedList] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = { case Fix(Some((head, tail))) => Some((head, tail)) case Nil => None}
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = { case Fix(Some((head, tail))) => Some((head, tail)) case Nil => None}
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = { case Fix(Some((head, tail))) => Some((head, tail)) case Fix(None) => None}
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = { case Fix(Some((head, tail))) => Some((head, tail)) case Fix(None) => None}
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = { case Fix(Some((head, tail))) => Some((head, tail)) case Fix(None) => None}
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = { case Fix(Some((head, tail))) => Some((head, tail)) case Fix(None) => None}
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = { case Fix(Some((head, tail))) => Some((head, tail)) case Fix(None) => None}
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = _.value
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = _.value
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = _.value
Fix
val projectFix: Fix[ListF] => ListF[Fix[ListF]] = _.value
Fix
def projectFix: Fix[ListF] => ListF[Fix[ListF]] = _.value
Fix
def projectFix[F[_]]: Fix[ListF] => ListF[Fix[ListF]] = _.value
Fix
def projectFix[F[_]]: Fix[ListF] => ListF[Fix[ListF]] = _.value
Fix
def projectFix[F[_]]: Fix[F] => F[Fix[F]] = _.value
Fix
def projectFix[F[_]]: Fix[F] => F[Fix[F]] = _.value
Fix
def cataFix[F[_]: Functor, A]( algebra: F[A] => A, project: Fix[F] => F[Fix[F]]): Fix[F] => A = { def loop(state: Fix[F]): A = algebra(map(project(state), loop)) loop}
Fix
def cataFix[F[_]: Functor, A]( algebra: F[A] => A, project: Fix[F] => F[Fix[F]]): Fix[F] => A = { def loop(state: Fix[F]): A = algebra(map(project(state), loop)) loop}
Fix
def cataFix[F[_]: Functor, A]( algebra: F[A] => A, project: Fix[F] => F[Fix[F]]): Fix[F] => A = { def loop(state: Fix[F]): A = algebra(map(state.value, loop)) loop}
Fix
def cataFix[F[_]: Functor, A]( algebra: F[A] => A, project: Fix[F] => F[Fix[F]]): Fix[F] => A = { def loop(state: Fix[F]): A = algebra(map(state.value, loop)) loop}
Fix
def cataFix[F[_]: Functor, A]( algebra: F[A] => A): Fix[F] => A = { def loop(state: Fix[F]): A = algebra(map(state.value, loop)) loop}
Fix
Fix
product
in terms of cataFix
val productFix: FixedList => Int = cataFix(productAlgebra)
product
in terms of cataFix
val productFix: FixedList => Int = cataFix(productAlgebra)
product
in terms of cataFix
val productFix: FixedList => Int = cataFix(productAlgebra)
product
in terms of cataFix
val productFix: FixedList => Int = cataFix(productAlgebra)
productFix(fixedInts)// res21: Int = 6
height
in terms of cataFix
val heightFix: FixedTree => Int = cataFix(heightAlgebra)
height
in terms of cataFix
val heightFix: FixedTree => Int = cataFix(heightAlgebra)
height
in terms of cataFix
val heightFix: FixedTree => Int = cataFix(heightAlgebra)
height
in terms of cataFix
val heightFix: FixedTree => Int = cataFix(heightAlgebra)
heightFix(fixedIntTree)// res22: Int = 3
Fix
def headOpt(list: FixedList): Option[Int] = list match { case Fix(Some((head, _))) => Some(head) case Fix(None) => None}
Fix
def headOpt(list: List): Option[Int] = list match { case Cons( head, _) => Some(head) case Nil => None}
Fix
val list: FixedList = Fix[ListF](Some((3, Fix[ListF](Some((2, Fix[ListF](Some((1, Fix[ListF](None) ))) ))) )))
Fix
val list: List = Cons( 3, Cons( 2, Cons( 1, Nil ) ) )
Using Fix
makes:
Using Fix
makes:
Using Fix
makes:
the hard case easier.
the easy case harder.
Using Fix
makes:
the hard case easier.
the easy case harder.
little sense.
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))// res24: String = 3 :: 2 :: 1 :: nil
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def range( from: Int): List = { if(from > 0) Cons(from, range(from - 1)) else Nil}
mkString(range(3))
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
mkString(charCodes("cata"))// res25: String = 99 :: 97 :: 116 :: 97 :: nil
Generative recursion is composed of:
Generative recursion is composed of:
Generative recursion is composed of:
a predicate that tells us whether to keep recursing.
a way of extracting a value and a new state from a given state.
Generative recursion is composed of:
a predicate that tells us whether to keep recursing.
a way of extracting a value and a new state from a given state.
some recursive structure around these elements.
charCodes
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
charCodes
def charCodes( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, charCodes(from.tail)) else Nil}
charCodes
def recurse( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, recurse(from.tail)) else Nil}
charCodes
def recurse( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, recurse(from.tail)) else Nil}
mkString(recurse("cata"))// res26: String = 99 :: 97 :: 116 :: 97 :: nil
charCodes
charCodes
charCodes
charCodes
charCodes
charCodes
charCodes
charCodes
charCodes
charCodes
def recurse( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, recurse(from.tail)) else Nil}
def recurse( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, recurse(from.tail)) else Nil}
def predicate(from: String): Boolean = from.nonEmpty
def recurse( from: String): List = { if(from.nonEmpty) Cons(from.head.toInt, recurse(from.tail)) else Nil}
def predicate(from: String): Boolean = from.nonEmpty
def recurse( from: String): List = { if(predicate(from)) Cons(from.head.toInt, recurse(from.tail)) else Nil}
def predicate(from: String): Boolean = from.nonEmpty
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) Cons(from.head.toInt, recurse(from.tail)) else Nil}
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) Cons(from.head.toInt, recurse(predicate, from.tail)) else Nil}
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) Cons(from.head.toInt, recurse(predicate, from.tail)) else Nil}
mkString(recurse(predicate, "cata"))// res27: String = 99 :: 97 :: 116 :: 97 :: nil
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) Cons(from.head.toInt, recurse(predicate, from.tail)) else Nil}
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) Cons(from.head.toInt, recurse(predicate, from.tail)) else Nil}
def update(from: String): (Int, String) = (from.head.toInt, from.tail)
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) Cons(from.head.toInt, recurse(predicate, from.tail)) else Nil}
def update(from: String): (Int, String) = (from.head.toInt, from.tail)
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, nextState)) } else Nil}
def update(from: String): (Int, String) = (from.head.toInt, from.tail)
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, nextState)) } else Nil}
def update(from: String): (Int, String) = (from.head.toInt, from.tail)
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, nextState)) } else Nil}
def update(from: String): (Int, String) = (from.head.toInt, from.tail)
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, nextState)) } else Nil}
def update(from: String): (Int, String) = (from.head.toInt, from.tail)
def recurse( predicate: String => Boolean, from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, nextState)) } else Nil}
def update(from: String): (Int, String) = (from.head.toInt, from.tail)
def recurse( predicate: String => Boolean, update : String => (Int, String), from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, nextState)) } else Nil}
def recurse( predicate: String => Boolean, update : String => (Int, String), from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
def recurse( predicate: String => Boolean, update : String => (Int, String), from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
mkString(recurse(predicate, update, "cata"))// res28: String = 99 :: 97 :: 116 :: 97 :: nil
def recurse( predicate: String => Boolean, update : String => (Int, String), from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
def recurse[A]( predicate: String => Boolean, update : String => (Int, String), from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
def recurse[A]( predicate: String => Boolean, update : String => (Int, String), from : String): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
mkString(recurse(predicate, update, "cata"))// res29: String = 99 :: 97 :: 116 :: 97 :: nil
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { if(predicate(from)) { val (head, nextState) = update(from) Cons(head, recurse(predicate, update, nextState)) } else Nil}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop(from)}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop(from)}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop(from)}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop(from)}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop(from)}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop(from)}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A), from : A): List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop(from)}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A)): List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A)): List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A)): A => List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
def recurse[A]( predicate: A => Boolean, update : A => (Int, A)): A => List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
mkString(recurse(predicate, update)("cata"))// res30: String = 99 :: 97 :: 116 :: 97 :: nil
def recurse[A]( predicate: A => Boolean, update : A => (Int, A)): A => List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
def unfold[A]( predicate: A => Boolean, update : A => (Int, A)): A => List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
def unfold[A]( predicate: A => Boolean, update : A => (Int, A)): A => List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
mkString(unfold(predicate, update)("cata"))// res31: String = 99 :: 97 :: 116 :: 97 :: nil
range
as an unfoldval range: Int => List = unfold[Int]( predicate = state => state > 0, update = state => (state, state - 1) )
range
as an unfoldval range: Int => List = unfold[Int]( predicate = state => state > 0, update = state => (state, state - 1) )
range
as an unfoldval range: Int => List = unfold[Int]( predicate = state => state > 0, update = state => (state, state - 1) )
range
as an unfoldval range: Int => List = unfold[Int]( predicate = state => state > 0, update = state => (state, state - 1) )
range
as an unfoldval range: Int => List = unfold[Int]( predicate = state => state > 0, update = state => (state, state - 1) )
mkString(range(3))// res32: String = 3 :: 2 :: 1 :: nil
Generative recursion is generalised by:
Generative recursion is generalised by:
Generative recursion is generalised by:
parameterising the predicate.
parameterising the state update.
Generative recursion is generalised by:
parameterising the predicate.
parameterising the state update.
... knowing the structure of your type.
def unfold[A]( predicate: A => Boolean, update : A => (Int, A)): A => List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
predicate
and update
predicate
and update
predicate
and update
def unfold[A]( predicate: A => Boolean, update : A => (Int, A)): A => List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
predicate
and update
val op: String => Option[(Int, String)] = state => { if(predicate(state)) Some(update(state)) else None }
predicate
and update
val op: String => Option[(Int, String)] = state => { if(predicate(state)) Some(update(state)) else None }
predicate
and update
val op: String => Option[(Int, String)] = state => { if(predicate(state)) Some(update(state)) else None }
predicate
and update
val op: String => Option[(Int, String)] = state => { if(state.nonEmpty) Some(update(state)) else None }
predicate
and update
val op: String => Option[(Int, String)] = state => { if(state.nonEmpty) Some(update(state)) else None }
predicate
and update
val op: String => Option[(Int, String)] = state => { if(state.nonEmpty) Some(update(state)) else None }
predicate
and update
val op: String => Option[(Int, String)] = state => { if(state.nonEmpty) Some((state.head.toInt, state.tail)) else None }
predicate
and update
val op: String => Option[(Int, String)] = state => { if(state.nonEmpty) Some((state.head.toInt, state.tail)) else None }
predicate
and update
val op: String => Option[(Int, String)] = state => { if(state.nonEmpty) Some((state.head.toInt, state.tail)) else None }
predicate
and update
val op: String => ListF[String] = state => { if(state.nonEmpty) Some((state.head.toInt, state.tail)) else None }
predicate
and update
val op: String => ListF[String] = state => { if(state.nonEmpty) Some((state.head.toInt, state.tail)) else None }
predicate
and update
def unfold[A]( predicate: A => Boolean, update : A => (Int, A)): A => List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
predicate
and update
def unfold[A]( op: A => ListF[A]): A => List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
predicate
and update
def unfold[A]( op: A => ListF[A]): A => List = { def loop(state: A): List = if(predicate(state)) { val (head, nextState) = update(state) Cons(head, loop(nextState)) } else Nil loop}
predicate
and update
def unfold[A]( op: A => ListF[A]): A => List = { def loop(state: A): List = op(state) match { case Some((head, nextState)) => Cons(head, loop(nextState)) case None => Nil } loop}
predicate
and update
def unfold[A]( op: A => ListF[A]): A => List = { def loop(state: A): List = op(state) match { case Some((head, nextState)) => Cons(head, loop(nextState)) case None => Nil } loop}
predicate
and update
def unfold[A]( op: A => ListF[A]): A => List = { def loop(state: A): List = op(state) match { case Some((head, nextState)) => Cons(head, loop(nextState)) case None => Nil } loop}
predicate
and update
def unfold[A]( op: A => ListF[A]): A => List = { def loop(state: A): List = op(state) match { case Some((head, nextState)) => Cons(head, loop(nextState)) case None => Nil } loop}
predicate
and update
def unfold[A]( op: A => ListF[A]): A => List = { def loop(state: A): List = op(state) match { case Some((head, nextState)) => Cons(head, loop(nextState)) case None => Nil } loop}
predicate
and update
def unfold[A]( op: A => ListF[A]): A => List = { def loop(state: A): List = op(state) match { case Some((head, nextState)) => Cons(head, loop(nextState)) case None => Nil } loop}
predicate
and update
def unfold[A]( op: A => ListF[A]): A => List = { def loop(state: A): List = op(state) match { case Some((head, nextState)) => Cons(head, loop(nextState)) case None => Nil } loop}
mkString(unfold(op)("cata"))// res33: String = 99 :: 97 :: 116 :: 97 :: nil
predicate
and update
predicate
and update
def unfold[A]( op: A => ListF[A]): A => List = { def loop(state: A): List = op(state) match { case Some((head, state)) => Cons(head, loop(state)) case None => Nil } loop}
val embed: Option[(Int, List)] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
val embed: Option[(Int, List)] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
val embed: Option[(Int, List)] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
val embed: Option[(Int, List)] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
val embed: Option[(Int, List)] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
val embed: Option[(Int, List)] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
val embed: Option[(Int, List)] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
val embed: ListF[List] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
val embed: ListF[List] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
def unfold[A]( op : A => ListF[A]): A => List = { def loop(state: A): List = op(state) match { case Some((head, state)) => Cons(head, loop(state)) case None => Nil } loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = op(state) match { case Some((head, state)) => Cons(head, loop(state)) case None => Nil } loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = op(state) match { case Some((head, state)) => Cons(head, loop(state)) case None => Nil } loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = op(state) match { case Some((head, state)) => embed(Some((head, loop(state)))) case None => Nil } loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = op(state) match { case Some((head, state)) => embed(Some((head, loop(state)))) case None => Nil } loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = op(state) match { case Some((head, state)) => embed(Some((head, loop(state)))) case None => embed(None) } loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = op(state) match { case Some((head, state)) => embed(Some((head, loop(state)))) case None => embed(None) } loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = op(state) match { case Some((head, state)) => embed(Some((head, loop(state)))) case None => embed(None) } loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(op(state) match { case Some((head, state)) => Some((head, loop(state))) case None => None }) loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(op(state) match { case Some((head, state)) => Some((head, loop(state))) case None => None }) loop}
mkString(unfold(op, embed)("cata"))// res34: String = 99 :: 97 :: 116 :: 97 :: nil
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(op(state) match { case Some((head, state)) => Some((head, loop(state))) case None => None }) loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(op(state) match { case Some((head, state)) => Some((head, loop(state))) case None => None }) loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(op(state) match { case Some((head, state)) => Some((head, loop(state))) case None => None }) loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(op(state) match { case Some((head, state)) => Some((head, loop(state))) case None => None }) loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(op(state) match { case Some((head, state)) => Some((head, loop(state))) case None => None }) loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(op(state) match { case Some((head, state)) => Some((head, loop(state))) case None => None }) loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
mkString(unfold(op, embed)("cata"))// res35: String = 99 :: 97 :: 116 :: 97 :: nil
ListF
ListF
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
ListF
def unfold[A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
ListF
def unfold[F[_]: Functor, A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
ListF
def unfold[F[_]: Functor, A]( op : A => ListF[A], embed: ListF[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
ListF
def unfold[F[_]: Functor, A]( op : A => F[A], embed: F[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
ListF
def unfold[F[_]: Functor, A]( op : A => F[A], embed: F[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
mkString(unfold(op, embed).apply("cata"))// res36: String = 99 :: 97 :: 116 :: 97 :: nil
ListF
ListF
List
List
def unfold[F[_]: Functor, A]( op : A => F[A], embed: F[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
List
def unfold[F[_]: Functor, A, B]( op : A => F[A], embed: F[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
List
def unfold[F[_]: Functor, A, B]( op : A => F[A], embed: F[List] => List): A => List = { def loop(state: A): List = embed(map(op(state), loop)) loop}
List
def unfold[F[_]: Functor, A, B]( op : A => F[A], embed: F[B] => B): A => B = { def loop(state: A): B = embed(map(op(state), loop)) loop}
List
def unfold[F[_]: Functor, A, B]( op : A => F[A], embed: F[B] => B): A => B = { def loop(state: A): B = embed(map(op(state), loop)) loop}
mkString(unfold(op, embed).apply("cata"))// res37: String = 99 :: 97 :: 116 :: 97 :: nil
List
List
List
def unfold[F[_]: Functor, A, B]( op : A => F[A], embed: F[B] => B): A => B = { def loop(state: A): B = embed(map(op(state), loop)) loop}
def ana[F[_]: Functor, A, B]( op : A => F[A], embed: F[B] => B): A => B = { def loop(state: A): B = embed(map(op(state), loop)) loop}
def ana[F[_]: Functor, A, B]( op : A => F[A], embed: F[B] => B): A => B = { def loop(state: A): B = embed(map(op(state), loop)) loop}
def ana[F[_]: Functor, A, B]( coAlgebra: A => F[A], embed : F[B] => B): A => B = { def loop(state: A): B = embed(map(coAlgebra(state), loop)) loop}
def ana[F[_]: Functor, A, B]( coAlgebra: A => F[A], embed : F[B] => B): A => B = { def loop(state: A): B = embed(map(coAlgebra(state), loop)) loop}
mkString(ana(op, embed).apply("cata"))// res38: String = 99 :: 97 :: 116 :: 97 :: nil
range
as an anaval rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}val range: Int => List = ana(rangeCoAlgebra, embed)
range
as an anaval rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}val range: Int => List = ana(rangeCoAlgebra, embed)
range
as an anaval rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}val range: Int => List = ana(rangeCoAlgebra, embed)
range
as an anaval rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}val range: Int => List = ana(rangeCoAlgebra, embed)
range
as an anaval rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}val range: Int => List = ana(rangeCoAlgebra, embed)
range
as an anaval rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}val range: Int => List = ana(rangeCoAlgebra, embed)
range
as an anaval rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}val range: Int => List = ana(rangeCoAlgebra, embed)
mkString(range(3))// res39: String = 3 :: 2 :: 1 :: nil
Anamorphisms are:
Anamorphisms are:
Anamorphisms are:
generative recursion for types that can be embedded from a pattern functor.
fare less complicated than their names make them out to be.
Anamorphisms are:
generative recursion for types that can be embedded from a pattern functor.
fare less complicated than their names make them out to be.
suspiciously similar to catamorphisms...
cata
and ana
cata
and ana
cata
and ana
cata
and ana
cata
and ana
cata
and ana
cata
and ana
cata
and ana
cata
and ana
cata
and ana
cata
and ana
cata
and ana
val factorial: Int => Int = range andThen product
cata
and ana
val factorial: Int => Int = range andThen product
cata
and ana
val factorial: Int => Int = range andThen product
cata
and ana
val factorial: Int => Int = range andThen product
cata
and ana
val factorial: Int => Int = range andThen product
factorial(3)// res40: Int = 6
cata
and ana
val showRange: Int => String = range andThen mkString
cata
and ana
val showRange: Int => String = range andThen mkString
cata
and ana
val showRange: Int => String = range andThen mkString
cata
and ana
val showRange: Int => String = range andThen mkString
cata
and ana
val showRange: Int => String = range andThen mkString
showRange(3)// res41: String = 3 :: 2 :: 1 :: nil
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
3
ana andThen cata
ana andThen cata
3 // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
3 // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, 2)) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, 2)) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, 2)) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, 2)) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, Some((2, 1))) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, Some((2, 1))) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, Some((2, 1))) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, Some((2, 1))) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, Some((2, Some((1, 0))))) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, Some((2, Some((1, 0))))) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, Some((2, Some((1, 0))))) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, Some((2, Some((1, 0))))) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebra
val rangeCoAlgebra: Int => ListF[Int] = i => { if(i > 0) Some((i, i - 1)) else None}
ana andThen cata
ana andThen cata
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebra // embed
val embed: ListF[List] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebra // embed
val embed: ListF[List] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( Cons( Cons( ))) // embed
val embed: ListF[List] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( Cons( Cons( ))) // embed
val embed: ListF[List] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( Cons( Cons( Nil ))) // embed
val embed: ListF[List] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( Cons( Cons( Nil ))) // embed
val embed: ListF[List] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embed
val embed: ListF[List] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embed
val embed: ListF[List] => List = { case Some((head, tail)) => Cons(head, tail) case None => Nil}
ana andThen cata
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embed // project
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embed // project
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome(( Some(( Some(( ))))) // project
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome(( Some(( Some(( ))))) // project
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome(( Some(( Some(( None))))) // project
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome(( Some(( Some(( None))))) // project
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // project
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // project
val project: List => ListF[List] = { case Cons(head, tail) => Some((head, tail)) case Nil => None}
ana andThen cata
ana andThen cata
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // project // mkStringAlgebra
val mkStringAlgebra: ListF[String] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // project // mkStringAlgebra
val mkStringAlgebra: ListF[String] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // projectstep( step( step( ))) // mkStringAlgebra
val mkStringAlgebra: ListF[String] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // projectstep( step( step( ))) // mkStringAlgebra
val mkStringAlgebra: ListF[String] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // projectstep( step( step( base))) // mkStringAlgebra
val mkStringAlgebra: ListF[String] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // projectstep( step( step( base))) // mkStringAlgebra
val mkStringAlgebra: ListF[String] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // projectstep( 3, step( 2, step( 1, base))) // mkStringAlgebra
val mkStringAlgebra: ListF[String] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // projectstep( 3, step( 2, step( 1, base))) // mkStringAlgebra
val mkStringAlgebra: ListF[String] => String = { case Some((head, tailResult)) => step(head, tailResult) case None => base}
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // projectstep( 3, step( 2, step( 1, base))) // mkStringAlgebra
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // projectstep( 3, step( 2, step( 1, base))) // mkStringAlgebra
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebraCons( 3, Cons( 2, Cons( 1, Nil ))) // embedSome((3, Some((2, Some((1, None))))) // projectstep( 3, step( 2, step( 1, base))) // mkStringAlgebra
ana andThen cata
Some((3, Some((2, Some((1, None))))) // rangeCoAlgebrastep( 3, step( 2, step( 1, base))) // mkStringAlgebra
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
ana andThen cata
def ana[F[_]: Functor, A, B]( coAlgebra: A => F[A], embed : F[B] => B): A => B = { def loop(state: A): B = embed(map(coAlgebra(state), loop)) loop}
ana andThen cata
def ana[F[_]: Functor, A, B]( coAlgebra: A => F[A], embed : F[B] => B): A => B = { def loop(state: A): B = embed(map(coAlgebra(state), loop)) loop}
ana andThen cata
def ana[F[_]: Functor, A, B]( coAlgebra: A => F[A], algebra : F[B] => B): A => B = { def loop(state: A): B = algebra(map(coAlgebra(state), loop)) loop}
ana andThen cata
def ana[F[_]: Functor, A, B]( coAlgebra: A => F[A], algebra : F[B] => B): A => B = { def loop(state: A): B = algebra(map(coAlgebra(state), loop)) loop}
ana andThen cata
def showRange: Int => String = ana(rangeCoAlgebra, mkStringAlgebra)
ana andThen cata
def showRange: Int => String = ana(rangeCoAlgebra, mkStringAlgebra)
ana andThen cata
def showRange: Int => String = ana(rangeCoAlgebra, mkStringAlgebra)
ana andThen cata
def showRange: Int => String = ana(rangeCoAlgebra, mkStringAlgebra)
ana andThen cata
def showRange: Int => String = ana(rangeCoAlgebra, mkStringAlgebra)
ana andThen cata
def showRange: Int => String = ana(rangeCoAlgebra, mkStringAlgebra)
showRange(3)// res42: String = 3 :: 2 :: 1 :: nil
def ana[F[_]: Functor, A, B]( coAlgebra: A => F[A], algebra : F[B] => B): A => B = { def loop(state: A): B = algebra(map(coAlgebra(state), loop)) loop}
def hylo[F[_]: Functor, A, B]( coAlgebra: A => F[A], algebra : F[B] => B): A => B = { def loop(state: A): B = algebra(map(coAlgebra(state), loop)) loop}
def hylo[F[_]: Functor, A, B]( coAlgebra: A => F[A], algebra : F[B] => B): A => B = { def loop(state: A): B = algebra(map(coAlgebra(state), loop)) loop}
def hylo[F[_]: Functor, A, B]( coAlgebra: A => F[A], algebra : F[B] => B): A => B = { def loop(state: A): B = algebra(map(coAlgebra(state), loop)) loop}
def hylo[F[_]: Functor, A, B]( coAlgebra: B => F[B], algebra : F[A] => A): B => A = { def loop(state: B): A = algebra(map(coAlgebra(state), loop)) loop}
def hylo[F[_]: Functor, A, B]( coAlgebra: B => F[B], algebra : F[A] => A): B => A = { def loop(state: B): A = algebra(map(coAlgebra(state), loop)) loop}
def hylo[F[_]: Functor, A, B]( algebra : F[A] => A, coAlgebra: B => F[B]): B => A = { def loop(state: B): A = algebra(map(coAlgebra(state), loop)) loop}
def hylo[F[_]: Functor, A, B]( algebra : F[A] => A, coAlgebra: B => F[B]): B => A = { def loop(state: B): A = algebra(map(coAlgebra(state), loop)) loop}
def hylo[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
def hylo[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
def cata[F[_]: Functor, A, B]( algebra: F[A] => A, project: B => F[B]): B => A = { def loop(state: B): A = algebra(map(project(state), loop)) loop}
catamorphisms and anamorphisms are duals of each other.
they're also the same thing.
catamorphisms and anamorphisms are duals of each other.
they're also the same thing.
yes, this gives me a headache too.
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
Number + Return | Go to specific slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |