Created
June 14, 2022 00:41
-
-
Save rbobillot/90e5a7ce4ed578bfffe2f7871105b4f7 to your computer and use it in GitHub Desktop.
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
object Main { | |
import scala.language.higherKinds | |
/** | |
* Functor contains a function | |
* that maps from a category to another | |
*/ | |
trait Functor[F[_]] { | |
def map[A, B](fa: F[A])(f: A => B): F[B] | |
} | |
/** | |
* Comonad, like a Monad, is a Functor | |
* Comonad, is actually kind of the opposite of a Monad | |
* unit becomes counit : A => M[A] becomes C[A] => A | |
* join becomes cojoin : M[M[A]] => M[A] becomes C[A] => C[C[A]] | |
* >>= becomes =>> : M[A] => (A => M[B]) => M[B] becomes C[A] => (C[A] => B) => C[A] | |
*/ | |
trait Comonad[C[_]] extends Functor[C] { | |
def coUnit[A](ca: C[A]): A | |
def coJoin[A](ca: C[A]): C[C[A]] | |
def map[A, B](ca: C[A])(f: A => B): C[B] | |
def =>>[A, B](ca: C[A])(g: C[A] => B): C[B] | |
} | |
/** | |
* Instance of Comonad for List collection type | |
* coJoin returns a list of tails from a list: | |
* [1,2,3,4] : [[1,2,3,4],[2,3,4],[3,4],[4],[]] | |
*/ | |
val listComonad = new Comonad[List] { | |
def coUnit[A](ca: List[A]): A = ca.head | |
def coJoin[A](ca: List[A]): List[List[A]] = ca.tails.toList | |
def map[A, B](ca: List[A])(f: A => B): List[B] = for (a <- ca) yield f(a) | |
def =>>[A, B](ca: List[A])(g: List[A] => B): List[B] = map(coJoin(ca))(g) | |
} | |
/** | |
* slices uses the cobind function (=>>) from the Comonad pattern | |
* to simulate a `digits.sliding(n)` | |
* We could have used coJoin instead: | |
* listComonad coJoin (digits) map (_ take n) filter (_.size == n) | |
*/ | |
def slices(n: Int, digits: List[Int]): List[List[Int]] = | |
listComonad.=>>(digits)(_ take n).filter(_.size == n) | |
def main(av: Array[String]): Unit = | |
av.toList match { | |
case str :: n :: Nil if (str+n).forall(_.isDigit) => | |
println(slices(n.toInt, str.toList.map(_.asDigit)).map(_.mkString("[",",","]")).mkString("[",",","]")) | |
case _ => | |
println("run with: scala comonad.scala <digits:string> <windowing:int>") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment