2016-12-23 3 views
1

Je n'aime pas déstructurer les valeurs typées sum avec la correspondance de modèle. Cela me semble étranger à cause de son style pointu. Je préfère écrire et utiliser les fonctions switch pour les types de somme.Déstructuration sans point avec GHC

Ma question concerne tout type de somme généralement, mais je démontrer sur Either comme exemple:

data Processor cl cr r = MakeProcessor { l :: cl -> r, r :: cr -> r } 

switch :: Processor cl cr r -> Either cl cr -> r 
switch p ei = 
    case ei of 
     Left x -> l p x 
     Right x -> r p x 

Avec cette extension Either:

au lieu de ceci:

map f e = 
    case e of 
     Left x -> Left x 
     Right x -> Right (f x) 

je peux écrire ceci:

map f = switch (MakeProcessor { l : Left, r : f >>> Right }) 

, que je me sens plus agréable pour la plupart des situations.

Pour écrire un tel type d'extension, les travaux d'extension [Processor, switch] sont des travaux mécaniques. Je me demande donc: est-il possible de faire en sorte que le compilateur [GHC] le fasse pour moi? Ou tout autre moyen de déstructurer des valeurs typées somme dans un style inutile?


Remarque: J'ai utilisé Either comme exemple. Either était un mauvais choix, car de nombreux lecteurs pensaient que ma question portait sur Either spécifiquement, et donc m'a indiqué either. Je l'ai utilisé un type de somme qui est pas dans la bibliothèque de base, comme

data Result a b = Fail a | Success b 
+0

Vous trouverez peut-être la bibliothèque «lens» utile. Cela vous permettrait d'écrire votre fonction 'map' en tant que' over _Right'. –

+0

Je suppose que _Right vient de TemplateHaskell, non? Peut-être que c'est trop strict, mais j'évitais TH parce que ce n'est pas compatible avec SafeHaskell. – libeako

+0

Mon exemple '' Sither' est juste un exemple de ma méthode pour éviter la correspondance de formes. C'est une version plus sûre de la fonction 'soit' dans la bibliothèque de base. Ma question ne concerne pas spécifiquement «Sither», je l'utilise uniquement à titre d'exemple. – libeako

Répondre

2

La réponse courte est non (en particulier sans Template Haskell). Cependant, comme beaucoup de constructions dans la programmation fonctionnelle, vous pouvez le retourner à l'envers. Utilisez un encodage Church/Scott (ils sont identiques lorsque le type de données n'est pas récursif).

newtype ChurchEither a b = ChurchEither { switch :: forall c. (a -> c) -> (b -> c) -> c } 

dans lequel vous obtenez l'éliminateur switch gratuitement, car il est la définition du type, mais vous devez écrire les constructeurs vous

left x = ChurchEither (\l r -> l x) 
right x = ChurchEither (\l r -> r x) 

donc vous avez vraiment rien gagné boilerplate- sage.

+0

Je considère votre première ligne comme la réponse à ma question. – libeako

4

La fonction either vous permet de spécifier des fonctions distinctes à appliquer à Left et Right valeurs dans une valeur Either a b:

switch p ei = either (l p) (r p) ei 

vous pouvez immédiatement déposer ei des deux côtés pour obtenir

switch p = either (l p) (r p) 

et vous peut utiliser l'instance Applicative pour les fonctions d'abandonner p:

switch = either <$> l <*> r 

Pour un type de somme arbitraire, vous devez fournir une appropriée catamorphisme, qui est le nom de fantaisie pour une fonction comme either qui réduit une valeur enveloppée par le type de somme au type encapsulé.

+0

Mon exemple '' Sither' est juste un exemple de ma méthode pour éviter la correspondance de formes. C'est une version plus sûre de la fonction 'soit' dans la bibliothèque de base. Ma question ne concerne pas spécifiquement «Sither», je l'utilise uniquement à titre d'exemple. – libeako

+1

Pourriez-vous expliquer dans quel sens votre méthode est plus sûre que 'soit'? –

+0

Plus de sécurité: Une erreur de codage possible consiste à inverser l'ordre des paramètres de 'soit'. Si le type de valeurs stockées dans 'Sither' est égal à il n'y aura pas d'erreur de frappe. 'Sither' est un mauvais exemple pour démontrer ce genre de possibilité d'erreur, mais je pense généralement pour d'autres types de somme le danger est réel. Par conséquent, je préfère mettre les fonctions du processeur dans un enregistrement, juste pour que je puisse les nommer. – libeako