Skip to content

Instantly share code, notes, and snippets.

@stasimus
Last active December 11, 2018 15:20
Show Gist options
  • Save stasimus/4618e4bec6cfc6f30a16da20135d88e6 to your computer and use it in GitHub Desktop.
Save stasimus/4618e4bec6cfc6f30a16da20135d88e6 to your computer and use it in GitHub Desktop.
final def to(n: Int): List[Int] = n match {
case 0 => Nil
case n => n :: to(n - 1)
}
def prod(list: List[Int]): Int = list match {
case Nil => 1
case head :: tail => head * prod(tail)
}
val sum: (Int, Int) => Int = _ + _
val curried: Int => Int => Int = sum.curried
def sumIsIso(a: Int, b: Int) = {
assert(sum(a, b) == curried(a)(b))
assert(sum(a, b) == Function.uncurried(curried)(a, b))
}
/**
* -Ywarn-value-discard
*/
def intFunction(): Unit = {
3
}
def stringFunction(): Unit = {
"3"
}
// Despite return types functions aren't isomorphic
assert(intFunction() == stringFunction())
abstract class Iso[T, U] {
def get(t: T): U
def reverseGet(u: U): T
}
class Int2String extends Iso[Int, String] {
override def get(t: Int): String = t.toString
override def reverseGet(u: String): Int = u.toInt
}
type ListAnamorphism[U, T] = U => List[T]
def listAnamorphismFactory[U, T](func: T => Option[(U, T)]): ListAnamorphism[T, U] = {
in: T =>
def ana(initial: T): List[U] = func(initial) match {
case None => Nil
case Some((current, next)) => current :: ana(next)
}
ana(in)
}
val listDestruct: ListAnamorphism[Int, Int] = listAnamorphismFactory { i: Int => if (i == 0) None else Some(i, i - 1) }
type ListCatamorphism[T, U] = List[T] => U
def listCatamorphism[T, U](value: U, func: (T, U) => U): ListCatamorphism[T, U] = {
def cata(list: List[T]): U = {
list match {
case Nil => value
case head :: tail => func(head, cata(tail))
}
}
cata
}
type ListCatamorphism[T, U] = List[T] => U
def listCatamorphismFactory[T, U](value: U, func: (T, U) => U): ListCatamorphism[T, U] = {
def cata(list: List[T]): U = {
list match {
case Nil => value
case head :: tail => func(head, cata(tail))
}
}
cata
}
type ListHylomorphism[U] = U => U
def listHylomorphism[U, T](cata: ListCatamorphism[T, U], ana: ListAnamorphism[U, T]): ListHylomorphism[U] = cata.compose(ana)
val factorial = listHylomorphism(prod, listDestruct)
assert(factorial(3) == 6)
def prod: List[Int] => Int = listCatamorphism[Int, Int](1, _ * _)
class EitherInt2String extends Iso[Either[String, Int], String] {
override def get(t: Either[String, Int]): String = t match {
case Left(l) => l
case Right(r) => r.toString
}
override def reverseGet(u: String): Either[String, Int] = {
Try(u.toInt).toEither.left.map(_ => u)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment