Nella documentazione per Data.Functor i seguenti due sono indicati come leggi del funtore, a cui tutti i funtori devono attenersi.Le leggi del funtore dimostrano la completa conservazione della struttura?
fmap id == id
fmap (f . g) == fmap f . fmap g
Il modo in cui la mia intuizione mi dice funtori dovrebbero lavorare è che essi dovrebbero essere "struttura preservare", o in altre parole, se si dispone di una funzione f :: a -> b
ed è inversa g :: b -> a
poi
fmap f . fmap g == id
Non sono stato in grado di realizzare un'implementazione di fmap
che aderirebbe alle prime due leggi e violerebbe la seconda, ma non è affatto una prova. Qualcuno può illuminarmi?
+1 Sono stato alle prese con domande simili ultimamente. C'è una cosa che mi infastidisce con questa formulazione intuitiva: per quanto riguarda le funzioni senza inversione? Sicuramente 'fmap (const" Foo ")' è una struttura che preserva anche in un certo senso? – duplode
Sì, ma non è possibile usare 'const" Foo "' per provare la legge vera - devi scegliere un'altra funzione. Non sto dicendo che i funtori sono validi solo per i tipi di funzioni che la legge racchiude. – kqr
@duplode immaginare un albero 'albero dati a = foglia | Nodo a [Albero a] '. Quando parliamo di "struttura" di 't :: Tree a' pensiamo a quanti sottoalberi ha ciascun nodo e come sono disposti questi sottoalberi. Quindi potresti dire che siamo interessati a 't' con _qualcosa nei suoi nodi_. E infatti possiamo catturarlo con 'fmap (const()) t'. – fizruk