cette fonction existe-t-elle déjà? (a -> b -> c) -> (d -> b) -> a -> d -> c
Tout est dans le titre, mais je vais développer. J'ai écris une fonction assez pratique (que j'ai appelé assez maladroitement "point2", censé signifier "équivalent de l'operateur (.), mais la seconde fonction n'est appliquée qu'au niveau du deuxieme argument de la premiere fonction"). Voici sa définition:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| point2 :: (a -> b -> c) -> (d -> b) -> (( a -> d -> c ))
-- les doubles parenthèses sont bien sur inutiles pour le compilateur. elles sont uniquement là pour impliquer que les utilisateurs vont considérer la fonction comme retournant une autre fonction
-- bien qu'évidemment celle-ci peut être appliquée directement, retournant une valeur de type c, ou peut-être (d -> c) si application partielle.
-- J'ai nommé les variables dans le pattern avec les mêmes lettres que leurs types respectifs, pour "clarité"
point2 f g a d = f a (g d)
-- j'avais originellement écrit cette fonction en "point-free" style (je ne sais pas comment ça se dit en français)
-- avec l'aide de la fonction flip, qui provient de Data.Function (pour être franc a l'origine j'avais surtout réinventé ma propre roue);
-- donc, définition alternative en utilisant flip == (\f y x -> f x y)
point2 f g = flip (flip f . g)
-- preuve par décomposition: (ou bien peut etre "composition", vu qu'on ne decompose en fait rien du tout?)
-- f :: a -> b -> c
-- flip f :: b -> a -> c
-- flip f . g :: d -> a -> c
-- flip (flip f . g) == f `point2` g :: a -> d -> c |
en tout cas, c'est plutot utile si l'on veut combiner f et g mais avec g supposé retourner le *deuxieme* argument de f, pas le premier (ce qui serait le cas pour l'operateur (.))
Code:
(f a) . g == (f `point2` g) a
dans l'expression de gauche, "a" doit etre donné pour utiliser cette définition en "point-free" style; dans le second cas, "a" peut être omit, et on peut alors écrire "foo = f `point2` g", ce qui est bien plus proche du style "point-free", et bien plus simple à comprendre à mon avis, une fois que l'on a assimilé ce que fait cette fonction "point2".
Si vous avez suivi depuis le début, ma question est donc: est-ce que cette fonction existe déjà officiellement quelque part; je n'ai pas envie de réinventer la roue, et je suis curieux du nom que cette fonction pourrait porter, pare que je ne suis pas mortellement satisfait de "point2". j'adorerais un truc du genre (.2) mais ça n'est pas compatible avec haskell.
Aussi, j'avais oublié, même question pour la fonction suivante, encore une petite soeur de la fonction (.). Ici le but est de pouvoir écrire h a b = f (g a b) en mode "point-free".
Code:
1 2 3
| after2 :: (c -> d) -> (a -> b -> c) -> (( a -> b -> d ))
after2 f g a b = f (g a b)
-- le nom de cette fonction implique un usage infixe, par exemple for example: h = f `after2` g |
si vous connaissez Data.Function(on), en gros "after2" est un peu son opposée, ou l'une d'entre elles: `on` appliques g aux deux arguments de f indépendamment, avant de donner les deux résultats à f qui elle prends effectivement deux arguments (maximum, devrais-je dire):
Code:
1 2 3
| on :: (c -> c -> d) -> (e -> c) -> (( e -> e -> d ))
-- (f `on` g) a b == f (g a) (g b)
-- a et b sont de type "e" bien sur |
Accessoirement, je suis pratiquement sur que l'ont peut écrire:
Code:
1 2 3 4 5
| f `after2` g == curry (f . (uncurry g))
-- puisque, en utilisant la meme notation que la definition de after2 ci dessus:
-- uncurry g :: (a,b) -> c
-- f . uncurry g :: (a,b) -> d
-- curry (f . uncurry g) :: a -> b -> d |
Au cas où, les définitions des deux fonctions (un)curry:
Code:
1 2 3 4 5 6
| curry :: ((a,b) -> c) -> a -> b -> c
-- curry f a b = f (a,b)
-- curry f :: a -> b -> c, lorsque f :: (a,b) -> c
uncurry :: (a -> b -> c) -> (a, b) -> c
-- uncurry g (a,b) = g a b
-- uncurry g :: (a,b) -> c, lorsque g :: a -> b -> c |