Question

Je veux appliquer une fonction 3 argument de différentes manières en fonction d'une valeur booléenne (un des arguments).

Je voudrais être en mesure de l'appliquer d'une manière infixe afin que je puisse enchaîner (exemple ci-dessous). quelque chose comme ce qui suit, mais qui fonctionne réellement.

f :: Bool -> a -> a -> a

f True  i j = i
f False i j = j

... y `(f True)` z `(f False)` b

Dois-je besoin d'avoir la Bool que la deuxième variable? Ou autre chose? Je suis un peu perdu.

P.S. la raison pour laquelle je voulais faire était d'avoir en option la fonction append

Était-ce utile?

La solution

Le infix notation pour les fonctions avec plus de deux arguments est possible, mais pas très agréable . Dans votre cas, étant donné

f :: Bool -> a -> a -> a
f True i j = i
f False i j = j

vous pouvez écrire

(True `f` 1) 3

Il est beaucoup plus facile (comme suggéré par d'autres) à écrire:

let ft = f True
let ff = f False

vous pouvez faire

1 `ft` 3 `ff` 5

Si vous voulez utiliser f vous devez écrire:

(False `f` ((True `f` 1) 3)) 5

Vous pouvez vérifier que

1 `ft` 3 `ff` 5 == (False `f` ((True `f` 1) 3)) 5

Autres conseils

Vous pouvez utiliser un opérateur d'application inverse pour obtenir un effet similaire. Cependant, pour chaque fixité de l'opérateur, vous devrez définir sa propre paire d'opérateurs.

Cela fonctionne:

infixl 5 -|
(-|) :: a -> (a -> b) -> b
(-|) = flip ($)

infixl 5 |-
(|-) :: (a -> b) -> a -> b
(|-) = ($)

infixr 5 =|
(|=) :: (a -> b -> c) -> b -> (a -> c)
(|=) = flip

infixr 5 |=
(=|) :: a -> (a -> c) -> c
(=|) = (-|)

f b x y = if b then x else y

main = do
    putStrLn $ "qwe" -| f True |- "asd" -| f False |- "kojo"
    putStrLn $ "qwe" =| f True |= "asd" =| f False |= "kojo"

et imprime:

kojo
qwe

Ici -| et supports |- joignons expressions infixes gauche associative et =| et joignons de |= expressions droit associatif.

Méfiez-vous que ce ne sont que des paires d'opérateurs indépendants, des messages d'erreur lorsque les abusant peuvent être tout à fait obscure.

Alors que infix expression syntaxe ont été proposées, ils n'ont pas été adoptées, au mieux de ma connaissance.

Vous pouvez envisager d'utiliser les fonctions ternaires de if then else, comme suit:

infix 0 ?
(?) :: Bool -> (t, t) -> t
c ? (t, e) = if c then t else e

Eh bien, pour une chose, f aurait le type f :: Bool -> a -> a -> a

Voir http://www.haskell.org/haskellwiki/Infix_operator#Using_prefix_functions_with_infix_notation pour plus d'informations sur l'utilisation des fonctions de préfixe dans un cadre infix.

Il faut espérer que quelqu'un d'autre est plus sage et peut expliquer pourquoi

1 `f True` 3 

ne fonctionne pas, puisque

ft = f True
1 `ft` 3

fonctionne très bien, et cela semble violer la transparence référentielle ...

Il semblerait qu'il n'y ait pas un « gentil », facile à faire, mais je suis sûr qu'il ya un certain modèle de niveau plus élevé que cela correspond, ou vous pouvez faire quelque chose avec, par exemple, zipWith ou plis .. .

Pourquoi avez-vous besoin de la fonction booléenne du tout? Si la valeur est jamais utilisé, pourquoi ne pas définir comme f

f :: a -> a -> a  
f i j  
i `f` j

Si le booléen est vraiment nécessaire, alors que Pvital suggéré, créer un ftrue et fFalse et utiliser celles-ci.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top