trait Comonad[M[_]] {
   // map
   def >>[A,B](a: M[A])(f: A => B): M[B]

   // extract | coeta 
   def counit[A](a:M[A]): A

   // coflatten | comu
   def cojoin[A](a: M[A]): M[M[A]]

object Comonad {

  implicit def listComonad[A]: Comonad[List]
    new Comonad[List] {

      def counit[A](lsa: List[A])
        lsa match { case List(a) => a }

      def cojoin[A](lsa:List[A]): List[List[A]]

      def >>[A,B](lsa: List[A])(f: A => B): List[B]
        lsa map f


So yeah I'm looking at this and I don't have that correct feeling...

Anyone mind correcting this and maybe offerring one or two other simple comonads?


1 Answer 1


I believe, what's bothering you is a non-total definition of counit, right? (for cojoin one possible variation is lsa.tails) Indeed, a List does not have a valid comonad instance specifically bacause of that. It does have a valid semicomonad instance though.

Things that have a valid comonad instance are, for example: Identity, NonEmptyList, Zipper, Tuple. Here's a reddit question with more examples of comonads.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.