Skip to content

Instantly share code, notes, and snippets.

@vpatryshev
Created November 13, 2022 17:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vpatryshev/49fec9fc9a49fe45d36234db5af81a03 to your computer and use it in GitHub Desktop.
Save vpatryshev/49fec9fc9a49fe45d36234db5af81a03 to your computer and use it in GitHub Desktop.
sample applicative functor in Scala that is not a monad
/**
* An example of a polynomial applicative functor `1+X×X` build from two monads, 1+ and X×X, and
* which is not a monad.
*
* Idea: https://stackoverflow.com/questions/49742377/is-data-poe-a-empty-pair-a-a-a-monad/49742857#49742857
*/
object NotMonad {
sealed trait SquarePlusOne[+A] {
def map[B](f: A => B): SquarePlusOne[B]
}
case object One extends SquarePlusOne[Nothing] {
def map[B](f: Nothing => B): SquarePlusOne[B] = One
}
case class Square[A](a: A, b: A) extends SquarePlusOne[A] {
def map[B](f: A => B): SquarePlusOne[B] = Square(f(a), f(b))
}
def flatten[A](nm2: SquarePlusOne[SquarePlusOne[A]]): SquarePlusOne[A] = nm2 match {
case Square(Square(a, b), Square(c, d)) => Square(a, d)
case _ => One
}
def main(args : Array[String]): Unit = {
val left1: SquarePlusOne[Int] =Square(1, 2)
val left2: SquarePlusOne[SquarePlusOne[Int]] = Square(left1, One)
val right1: SquarePlusOne[Int] = Square(3, 4)
val right2: SquarePlusOne[SquarePlusOne[Int]] = Square(One, right1)
val sample: SquarePlusOne[SquarePlusOne[SquarePlusOne[Int]]] =Square(left2, right2)
val sample1: SquarePlusOne[SquarePlusOne[Int]] = flatten(sample)
assert(sample1 == Square(left1, right1), s"$sample1 vs ${Square(left1, right2)}")
val flattenedFromOutside: SquarePlusOne[Int] = flatten(sample1)
assert(flattenedFromOutside == Square(1, 4))
assert(flatten(left2) == One)
assert(flatten(right2) == One)
val flattenedInside: SquarePlusOne[SquarePlusOne[Int]] = sample map flatten
assert(flattenedInside == Square(One, One), s"got $flattenedInside")
val flattenedFromInside: SquarePlusOne[Int] = flatten(flattenedInside)
assert(flattenedFromInside == One)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment