Monads get fmap
da Functor
typeclass. Perché le comonad non hanno bisogno di un metodo cofmap
definito in una classe Cofunctor
?Perché non esiste una classe di caratteri `Cofunctor` in Haskell?
risposta
Functor
è definito come:
class Functor f where
fmap :: (a -> b) -> (f a -> f b)
Cofunctor
potrebbe essere definito come segue:
class Cofunctor f where
cofmap :: (b -> a) -> (f b -> f a)
Così, entrambi sono tecnicamente lo stesso, ed è per questo Cofunctor
non esiste. "Il duplice concetto di 'functor in generale' è ancora 'functor in generale'".
Poiché Functor
e Cofunctor
sono uguali, sia le monadi che le comonone sono definite utilizzando Functor
. Ma non lasciare che ti faccia pensare che monadi e comonad siano la stessa cosa, non lo sono.
monade è definito (semplificando) come:
class Functor m => Monad where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
se un comonad (di nuovo, semplificato) è:
class Functor w => Comonad where
extract :: w a -> a
extend :: (w a -> b) -> w a -> w b
nota la "simmetria".
Un'altra cosa è un funtore controvariante, definito come:
import Data.Functor.Contravariant
class Contravariant f where
contramap :: (b -> a) -> (f a -> f b)
Non sarebbe il duale di un funtore C -> D un funtore D -> C? Quindi il duale di ** a ** functor non è lo stesso stesso funtore, ma il duplice concetto di "functor in generale" è ancora "functor in generale". Penso che sto solo suonando la semantica, ma il linguaggio in "un funtore è il doppio di sé" suona come l'affermazione che i singoli funtori sono in qualche modo utilizzabili come il loro stesso inverso, o qualcosa del genere. – Ben
@ Ben hai ragione. L'ho corretto –
@Ben Che più o meno scuote la definizione formale: https://en.wikipedia.org/wiki/Equivalence_of_categories#Definition – Zaaier
Per riferimento,
class Functor w => Comonad w where
extract :: w a -> a
duplicate :: w a -> w (w a)
extend :: (w a -> b) -> w a -> w b
instance Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
join :: Monad m => m (m a) -> m a
nota che, dato extract
e extend
è possibile produrre fmap
e duplicate
, e che, dato return
e >>=
è possibile produrre fmap
, pure
, <*>
e join
. Quindi possiamo concentrarci solo su pure
+ >>=
e extract
+ extend
.
immagino che potrebbe essere alla ricerca di qualcosa di simile
class InverseFunctor f where
unmap :: (f a -> f b) -> a -> b
Poiché la classe Monad
rende facile "mettere le cose in", mentre solo permette una sorta di approccio ipotetica a "prendere le cose fuori", e Comonad
fa qualcosa contro ciò, inizialmente la tua richiesta sembra ragionevole. Tuttavia, esiste una significativa asimmetria tra >>=
e extend
che ostacolerà qualsiasi tentativo di definire unmap
. Si noti in particolare che il primo argomento di >>=
ha tipo m a
. Il secondo argomento di extend
ha tipo w a
— nona
.
potremmo definire un unmap con: "unmap f = extract. F. Return" e digitare signature "unmap :: Monad f, Comonad f => (fa -> fb) -> a -> b" – Stratege
In realtà, ti sbagli: ce n'è uno!
Questo perché un cofunctor è la stessa di un funtore. Non c'è differenza tra i due. Tuttavia, monadi e comonad sono diversi. Esiste tuttavia un functor controvariante, con un metodo 'contramap' che ha il tipo' Contravariante f => (a -> b) -> f b -> f a'. Tuttavia, non è lo stesso di un cofunctor. –
Intendi "cofuntore" come duale di un funtore (che è solo un funtore, poiché è auto-duale), o per indicare un funtore che è controverso? http://math.stackexchange.com/questions/394472/is-cofunctor-an-accepted-term-for-contravariant-functors –