43 votes

Comment écrire un Haskell fonction qui prend un variadic fonction comme argument

Je suis en train de créer une fonction qui reçoit un variadic fonctionner comme un argument, c'est à dire

func :: (a -> ... -> a) -> a

comment puis-je accomplir?

J'ai lu sur polyvariadic fonctions et je suis sûr qu' Oleg a déjà fait, mais je suis perdu en essayant d'appliquer le modèle sur une fonction avec une variadic fonction comme argument. Surtout Olegs approche semble fonctionner avec glasgow extensions et je veux la solution de travailler dans le plus pur Haskell 98 (comme du Texte.Printf n').

La raison que je demande, c'est que je suis en train de construire une fonction qui prend une fonction booléenne comme argument et vérifie si c'est une tautologie, c'est à dire

isTautology :: (Bool -> ... -> Bool) -> Bool

que l'on pourrait, de type:

isTautology (\x -> x && not x)
isTautology (\x y -> x && y || not y)

Mon problème est que je lis sur le truc était de faire le type de retour d'une variable de type (de sorte qu'il peut être le résultat ou une autre fonction), mais mon retour est de type fixe (Bool).

56voto

hammar Points 89293

L'astuce est de faire une classe de type qui vous permettra de définir une instance pour les fonctions, et un exemple pour le type de retour. Le fait que c'est un Bool n'est pas un problème du tout.

Nous essayons d'écrire une fonction qui prend un variadic argument et renvoie un Bool, de sorte que nous allons définir une classe de type avec une telle fonction.

class Stmt a where
    tautology :: a -> Bool

Ensuite, nous définissons un exemple pour le type de retour de la variadic fonction. Dans ce cas, c'est Bool.

-- A Bool is a tautology if it's True.
instance Stmt Bool where
    tautology = id

L'élément clé est l'instance suivante pour des fonctions qui prennent un Bool d'argument, et dont le type de retour est un type de notre classe. De cette façon, cette instance sera appliqué plusieurs fois, si une fonction prend plusieurs arguments.

-- A function is a tautology if it always returns a tautology.
instance Stmt b => Stmt (Bool -> b) where
    tautology f = tautology (f True) && tautology (f False)

L'écriture de cette façon implique FlexibleInstances en raison de l' Bool dans la deuxième instance de la tête. Pour faire la même chose avec de la pure Haskell 98, nous aurons besoin d'utiliser un appareil de contrainte de type de variable à la place. Nous pouvons par exemple utiliser Bounded et Enum (il y a des exemples à la fois pour Bool), ou vous pouvez faire votre propre classe qui vous permettra de construire les éléments de réflexion pertinents.

instance (Enum a, Bounded a, Stmt b) => Stmt (a -> b) where
    tautology f = all (tautology . f) [minBound .. maxBound]

Et nous avons terminé. Essayons ceci:

> tautology $ \x y -> (not x && not y) == not (x && y)
False
> tautology $ \x y -> (not x && not y) == not (x || y)
True

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X