Question

De temps en temps, je trébuche sur le problème que je veux exprimer « s'il vous plaît utiliser le dernier argument deux fois », par exemple afin d'écrire le style Pointfree ou pour éviter un lambda. Par exemple.

sqr x = x * x

pourrait être écrit comme

sqr = doubleArgs (*) where
   doubleArgs f x = f x x

Ou considérer cette fonction un peu plus compliquée (prise cette question ):

ins x xs = zipWith (\ a b -> a ++ (x:b)) (inits xs) (tails xs)

Je pourrais écrire ce code Pointfree s'il y avait une fonction comme ceci:

ins x = dup (zipWith (\ a b -> a ++ (x:b))) inits tails where
     dup f f1 f2 x = f (f1 x) (f2 x)

Mais comme je ne peux pas trouver quelque chose comme doubleArgs ou dup dans Hoogle, donc je suppose que je pourrais manquer un truc ou idiome ici.

Était-ce utile?

La solution

De Control.Monad:

join :: (Monad m) -> m (m a) -> m a
join m = m >>= id

instance Monad ((->) r) where
    return = const
    m >>= f = \x -> f (m x) x

Expansion:

join :: (a -> a -> b) -> (a -> b)
join f = f >>= id
       = \x -> id (f x) x
       = \x -> f x x

Alors, oui, Control.Monad.join.

Oh, et pour votre exemple Pointfree, avez-vous essayé d'utiliser la notation applicative (de Control.Applicative):

ins x = zipWith (\a b -> a ++ (x:b)) <$> inits <*> tails

(je aussi ne sais pas pourquoi les gens sont si friands de a ++ (x:b) au lieu de a ++ [x] ++ b ... ce n'est pas plus rapide - le revêtement intérieur prendra soin - et celui-ci est bien plus symétrique Eh bien!)

Autres conseils

Ce que vous appelez « doubleArgs » est plus souvent appelé dup - il est le W combinateur (appelé dans la paruline Pour Mock a Mockingbird) - « le duplicateur élémentaire ».

Ce que vous appelez 'dup' est en fait le 'Starling prime' Combinator.

Haskell a une assez petite "base Combinator" voir Data.Function, ainsi que quelques opérations Applicative et monadiques ajouter plus combinators "standard" en vertu des instances de fonction pour Applicative et Monad (<*> de Applicative est le S - Starling Combinator pour l'instance fonctionnelle, liftA2 & liftM2 sont Starling-prime). Il ne semble pas être beaucoup d'enthousiasme dans la communauté pour l'expansion Data.Function, donc tout combinateurs sont amusants, pragmatiquement Je suis venu à préférer longue main dans les situations où un combinateur est pas directement disponible.

Voici une autre solution pour la deuxième partie de ma question: Flèches

import Control.Arrow

ins x = inits &&& tails >>> second (map (x:)) >>> uncurry (zipWith (++))

Le &&& ( « sortance ») distribue un argument à deux fonctions et renvoie la paire des résultats. >>> ( « et ») inverse l'ordre d'application de fonction, ce qui permet d'avoir une chaîne d'opérations de gauche à droite. second ne fonctionne que sur la deuxième partie d'une paire. Bien sûr, vous avez besoin d'un uncurry à la fin pour alimenter la paire dans une fonction attendant deux arguments.

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