Created
November 13, 2022 17:33
-
-
Save vpatryshev/49fec9fc9a49fe45d36234db5af81a03 to your computer and use it in GitHub Desktop.
sample applicative functor in Scala that is not a monad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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