It's easy to describe adjunction in Haskell:
class Functor f where
map :: (a -> b) -> f a -> f b
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
class Functor w => Comonad w where
extract :: w a -> a
duplicate :: w a -> w (w a)
class (Comonad w, Monad m) => Adjoint w m | w -> m, m -> w where
unit :: a -> m (w a)
counit :: w (m a) -> a
However, I struggle to show that StoreT s w
and StateT s m
are adjoint.
instance Adjoint w m => Adjoint (StoreT s w) (StateT s m) where
-- ...
GHC complains that m
cannot be determined by StoreT s w
because m
doesn't appear in StoreT s w
:
• Illegal instance declaration for
‘Adjoint (StoreT s w) (StateT s m)’
The coverage condition fails in class ‘Adjoint’
for functional dependency: ‘w -> m’
Reason: lhs type ‘StoreT s w’
does not determine rhs type ‘StateT s m’
Un-determined variable: m
Using UndecidableInstances might help
• In the instance declaration for
‘Adjoint (StoreT s w) (StateT s m)’
I don't really understand why this is a problem since w -> m
by Adjoint w m
. GHC further suggests turning on -XUndecidableInstances
. Would it be safe to do this in this case? Am I trying to do something impossible?