Reputation:
So given this encoding of a comonad (see below) are the comonad laws above it correct? for some reason I don't think they are from looking at them, and I know that heading off wrong from there will yield only bad road, so I'd appreciate the nudge, hint, help, answer what have you.
/**
* note: I think these are right
* Comonad Laws
*
* (i) counit(cojoin(m)) == m
*
* (ii) >>(counit(m))(cojoin) == m
*
* (iii) cojoin(cojoin(m)) == >>(cojoin(m))(cojoin)
*
*/
trait Comonad[M[_]] {
// map
def >>[A,B](a: M[A])(f: A => B): B
// extract | coeta
def counit[A](a:M[A]): A
// cobind | =<< | extend
def coflatMap[A,B](ma:M[A])(f: M[A] => B): M[B]
// coflatten | comu
def cojoin[A](a: M[A]): M[M[A]]
}
Upvotes: 4
Views: 351
Reputation: 1188
You are almost there. Both, (i)
and (iii)
are correct, but (ii)
is wrong. You can spot the mistake because (ii)
is not well typed: for >>(counit(m)
the argument counit(m)
has type A
rather than M[A]
.
The correct laws for your operations are:
* (i) counit(cojoin(m)) == m
*
* (ii) >>(cojoin(m))(counit) == m
*
* (iii) cojoin(cojoin(m)) == >>(cojoin(m))(cojoin)
Thus, for both (i)
and (ii)
, the law is that applying either counit
or the "map" of counit
to the result of a cojoin
is equivalent to the identity function.
Upvotes: 4