¿Truco para “reutilizar” argumentos en Haskell?
coding-style pointfree (3)
Aquí hay otra solución para la segunda parte de mi pregunta: ¡Flechas!
import Control.Arrow
ins x = inits &&& tails >>> second (map (x:)) >>> uncurry (zipWith (++))
El &&&
("fanout") distribuye un argumento a dos funciones y devuelve el par de los resultados. >>>
("y luego") invierte el orden de la aplicación de función, lo que permite tener una cadena de operaciones de izquierda a derecha. second
funciona solo en la segunda parte de un par. Por supuesto, necesita un uncurry
al final para alimentar al par en una función que espera dos argumentos.
De vez en cuando me tropiezo con el problema que quiero expresar "por favor, use el último argumento dos veces", por ejemplo, para escribir estilo libre de puntos o para evitar un lambda. P.ej
sqr x = x * x
podría ser escrito como
sqr = doubleArgs (*) where
doubleArgs f x = f x x
O considere esta función un poco más complicada (tomada de esta pregunta ):
ins x xs = zipWith (/ a b -> a ++ (x:b)) (inits xs) (tails xs)
Podría escribir este código sin punto si hubiera una función como esta:
ins x = dup (zipWith (/ a b -> a ++ (x:b))) inits tails where
dup f f1 f2 x = f (f1 x) (f2 x)
Pero como no puedo encontrar algo como doubleArgs o dup en Hoogle, supongo que podría faltar un truco o lenguaje aquí.
Desde 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
En expansión:
join :: (a -> a -> b) -> (a -> b)
join f = f >>= id
= /x -> id (f x) x
= /x -> f x x
Entonces, sí, Control.Monad.join
.
Ah, y para tu ejemplo de free point, has intentado usar la notación aplicativa (de Control.Applicative
):
ins x = zipWith (/a b -> a ++ (x:b)) <$> inits <*> tails
(Tampoco sé por qué a las personas les gusta tanto a ++ (x:b)
lugar de a ++ [x] ++ b
... no es más rápido: el inliner se encargará de eso, y este último es mucho más simétrico! Oh bien)
Lo que usted llama ''doubleArgs'' es más a menudo llamado dup - es el combinador W (llamado warbler en To Mocking Mockingbird) - "el duplicador elemental".
Lo que llamas ''dup'' es en realidad el combinador ''starling-prime''.
Haskell tiene una "base de combinador" bastante pequeña, consulte Data.Function, más algunas operaciones de Applicative y Monadic añaden más combinators de "standard" en virtud de las instancias de función para Applicative y Monad (<*> de Applicative es el combinador S-starling para el instancia funcional, liftA2 y liftM2 son starling-prime). No parece haber mucho entusiasmo en la comunidad para expandir Data.Function, así que mientras que los combinadores son muy divertidos, pragmáticamente prefiero la mano larga en situaciones donde un combinador no está disponible directamente.