2016-01-11 21 views
11

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?

+4

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. –

+0

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 –

risposta

19

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) 
+6

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

+0

@ Ben hai ragione. L'ho corretto –

+0

@Ben Che più o meno scuote la definizione formale: https://en.wikipedia.org/wiki/Equivalence_of_categories#Definition – Zaaier

3

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 anona.

+0

potremmo definire un unmap con: "unmap f = extract. F. Return" e digitare signature "unmap :: Monad f, Comonad f => (fa -> fb) -> a -> b" – Stratege