2016-03-08 29 views
5

Mentre studiavo più profondo Applicative sono venuto a Traversable, anche se conoscevo già Foldable da LYHGG, non ho visto il primo ancora, quindi ho iniziato a leggere il Haskell wiki about Traversable.pieghevole vs Traversable

Durante la lettura ho capito perché Foldable.fold è parallelo a Traversable.sequenceA e Foldable.foldMap è parallelo a Traversable.traverse.

ho visto anche che ogni Traversable è anche un Foldable e un Functor e sequenceA e traversal dispone di un'implementazione di default in termini di vicenda:

traverse f = sequenceA . fmap f 
sequenceA = traverse id 

Quindi, come ho visto in LYHGG che foldMap è una definizione completa minima per Foldable, ho pensato che è parallela a traverse, quindi fold (che è parallela a sequenceA) sarebbe anche una definizione completa minima (che non lo è) ... Foldable non è un Functor come Traversable è, quindi non possiamo applichiamo questo:

foldMap f = fold . fmap f 
fold = foldMap id -- this is ok 

Perché non è ogni Foldable un Functor, e che sarebbe un esempio di Foldable che in realtà non è un Functor?

+4

'Set' è un classico esempio di' Pieghevole' che non è un 'Functor'. Così sono i vettori unboxed. – dfeuer

+0

@dfeuer Leggerò di più su 'Set' per capire perché non è un' Functor', ma, Sets possono essere pensati come contenitori di cose che non si ripetono ... Detto questo, non riesco a capire rapidamente perché non è un'istanza di 'Functor' ... – FtheBuilder

+1

Il problema è che 'Functor' non dà alle implementazioni l'opportunità di limitare i loro argomenti di tipo. Immagina se qualcuno abbia scritto 'fmap f s' dove' f :: Int -> Integer -> Integer'. Il tipo "Integer -> Integer" non è nemmeno un'istanza di "Eq", tanto meno "Ord", quindi non c'è modo di verificare la presenza di duplicati durante la mappatura. La funzione potrebbe mappare più elementi a funzioni identiche e non avresti modo di comprimere i duplicati. – dfeuer

risposta

6

Come dice Dfeuer, Set è un buon esempio di Foldable che non è un Functor.

considerare il tipo di Set.map:

map :: Ord b => (a -> b) -> Set a -> Set b 

Si noti che questo è quasifmap, ma richiede un ulteriore Ord b vincolo. Poiché si dispone di questo vincolo, non è possibile creare un'istanza di Functor.

Nota che Set non è un functor su Haskell, anche con questa restrizione. Con un'impostazione intelligente delle istanze Eq possiamo infrangere la legge che fmap f . fmap g === fmap (f . g). Vedere questa domanda Stack Overflow per più vari discussione:

Sets, Functors and Eq confusion

Come notato lì, Setè un (endo) funtore sulla "sottocategoria di Hask" con i tipi ordinati come set e con mappe ordine preservando come morfismi.

Quindi, anche se non è evidente, il fatto che non siamo in grado di rendere un Set un functor allude effettivamente a un vero problema matematico e non solo a una limitazione del nostro macchinario di tipografia.

+0

quello che penso sia sorprendente è che matematicamente è un 'Functor' ma a causa di questo vincolo non può essere un' instance' del typeclass 'Functor' ... Non pensi che questo assomigli ad una" imperfezione "in la lingua? (Il linguaggio è davvero bello, conciso e potente, comunque!) – FtheBuilder

+0

@FtheBuilder Ho modificato la mia risposta per descrivere più contesto. – sclv

+0

So che non dovrei dire "Grazie" in un commento, ma in realtà, le tue spiegazioni erano veeeery interessanti! : D – FtheBuilder