2016-12-03 5 views
6

Une telle chose existe-t-elle dans le Prélude d'Haskell?Isomorphic `fmap` dans Haskell

wfmap :: Functor f 
     => a 
     -> (a -> b) 
     -> (b -> a) 
     -> (b -> f b) 
     -> f a 
wfmap x u w g = fmap (w) (g (u x)) 

Dans un projet, je travaille, je me suis souvent trouvé « conversion » d'un type à l'autre, le processus et « conversion » en arrière.

+0

Ne serait-il pas plus logique de prendre 'x :: a' comme dernier argument? – leftaroundabout

+0

@leftaroundabout oh ouais, c'est le cas. Merci d'avoir fait remarquer cela. Mais ce n'est qu'un pseudocode pour expliquer mon problème. C'est juste que j'ai beaucoup de fonctions et de types qui utilisent un modèle similaire à cela et je me demande s'il y a une meilleure façon de faire cela. – iluvAS

+2

Votre 'wfmap' déclare 5 arguments dans le type, mais seulement 4 dans la définition. Je pense que vous avez juste un argument supplémentaire de type 'a' dans le type. – chepner

Répondre

7

réordonner les arguments, comme leftaroundabout suggère, permet une définition plus net:

wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a 
wfmap u w g = fmap w . g . u 

En ce qui concerne le soutien aux bibliothèques, objectif fournit nifty support for isomorphisms. Un peu plus largement, comme le note Gurkenglas ...

Functor f => (b -> f b) -> a -> f a est aussi appelé Lens' a b et est la pièce maîtresse de la bibliothèque de l'objectif.

Sans plonger dans les détails de comment et pourquoi cela fonctionne, l'une des conséquences est que votre fonction peut être définie comme:

wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a 
wfmap u w g = (iso u w) g 

Ou encore:

wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a 
wfmap = iso 

wfmap est juste (une version spécialisée de) iso, qui donne une fonction qui peut être utilisée pour convertir une fonction b -> f b sur la "destination" d'isomorphisme en une a -> f a sur la isomorphisme "source".

Il est également intéressant de mentionner mapping, qui peut être utilisé à des fins quelque peu différente de l'application fmap de l'autre côté d'un isomorphisme:

GHCi> :t \u w g -> over (mapping (iso u w)) (fmap g) 
\u w g -> over (mapping (iso u w)) (fmap g) 
    :: Functor f => (s -> a) -> (b -> t) -> (a -> b) -> f s -> f t 
GHCi> :t \u w g -> under (mapping (iso u w)) (fmap g) 
\u w g -> under (mapping (iso u w)) (fmap g) 
    :: Functor f => (s -> a) -> (b -> a1) -> (a1 -> s) -> f b -> f a 

Enfin, notez que iso u w peut être remplacé par un Iso vous pourrait trouver dans les bibliothèques ou ont prédéfini ailleurs.

+0

Merci pour ça! :) – iluvAS