2012-05-30 56 views
7

Tengo una lambda \x f -> f x que se está utilizando en una operación foldM, donde x es un valor y f :: a -> b.Función Haskell para invertir la función llamada

¿Hay una función incorporada que hace esto?

¿Puedo reemplazar

foldM (\x f -> f x) ... 

con un poco de f'

foldM f' ... 

pensé que flip haría esto, pero se necesitan tres argumentos (flip :: (a -> b -> c) -> b -> a -> c)

Es probablemente similar a |> en F #.

Respuesta

20

Puede usar flip id o flip ($) (como ($) es solo un id especial para funciones):

Prelude> flip id 3 (+2) 
5 
Prelude> flip ($) 7 (>10) 
False 

Este es un uso interesante de la aplicación parcial: id f x con f siendo una función es simplemente f x. Obviamente, esto es también lo mismo que (flip id) x f, por lo que flip id es la función que está buscando.

Si se siente aventurero, intente inferir el tipo de flip id o flip ($) manualmente. Es divertido :)

+0

Wow, eso me llevó unos 5 minutos con papel y bolígrafo para resolver cómo la firma 'a -> a' de un id podía de alguna manera mapear a' flip' esperando algo con 'a - > b -> c'. ¡Vale la pena investigar un poco! – Ashe

+1

@Len: Se vuelve más claro una vez que se ve que cuando se aplica a las funciones, 'id' es lo mismo que' ($) ' –

+0

¡Eso es muy cierto! El momento "a-ha" para mí fue darme cuenta de que debería ver 'a -> b -> c' como' a -> (b -> c) 'que es, y luego coincidiría con' id' s 'a' -> a'' y descubrió que 'a = a' = (b -> c) '- Estaba mirando demasiado las diferencias de aridad y no podía superarlo. – Ashe

8

Sí, se llama flip :: (a -> b -> c) -> b -> a -> c, p. Ej. flip (>) 3 5 == True. Más información y fuente de pirateo: flip.

Lo que quiere es simplemente invertir los argumentos de la aplicación de función, ¿verdad? Bueno, ya que ($) es una aplicación de función, al usar flip puede escribir flip ($) :: b -> (b -> c) -> c. Veamos qué pasa. Esta es la fuente de las dos funciones de preludio:

-- from Hackage: 
($)      :: (a -> b) -> a -> b 
f $ x     = f x 

-- from Hackage: 
flip     :: (a -> b -> c) -> b -> a -> c 
flip f x y    = f y x 

Así que, básicamente, si usted junta los tipos, flip ($) convierte

flip ($) :: 
    b  -> -- type of x, argument of y and second argument of ($) 
    (b -> c) -> -- type of y, function applied by ($) as its first argument 
    c  -> -- result of the application "y x" 

Si sigue las definiciones actuales de las funciones:

flip ($) = (\f x y -> f y x) ($) -- from flip's def. 
     = \x y -> ($) y x   -- partial application 
     = y x      -- from ($)'s def. 
Cuestiones relacionadas