2011-11-19 13 views
7

Se supone que debo tomar este código:Reutilizando una función lambda en Haskell

f x y z = x^3 - g (x + g (y - g z) + g (z^2)) 
where g x = 2*x^2 + 10*x + 1 

y volver a escribir sin que (o dejar).

que significan para escribirlo con una función lambda (\ x -> ...)

Estoy intentando volver a utilizar una función lambda en Haskell. ¿Algunas ideas?

+6

'f = flip flip ((1 +) ap ((+). (2 *). (^ 2)) (10 *)). (dar la vuelta .) . ap ((.). (.). (.). (-). (^ 3)) (((ap id.).). flip flip (flip id. (^ 2)). (liftM2 (liftM2 (+)).). (. ((ap id.). (. flip id). (.). (-))). (.). (.). (+)) ': f hecho inútil por lambdabot – fuz

Respuesta

12

Como consejos bravit en, puede volver a escribir un no-recursivo let utilizando un lambda de la siguiente manera:

let x = A in B  ==>  (\x -> B) A 

donde x es una variable y A y B son expresiones.

+5

Lo que me parece gracioso acerca de este truco es que en realidad es una práctica estándar en Javascript ya que solo las funciones pueden introducir un bloque de alcance allí. – hugomg

+1

Todavía no estoy seguro de entender cómo se puede reutilizar – Asaf

+0

@Asaf: puede referirse a 'x' varias veces en' B'. Por ejemplo, tome '(\ x -> x + x) 3'. Esto es equivalente a '3 + 3', excepto que solo tuvo que escribir el' 3' una vez. – hammar

8

Para reutilizar algo, puede convertirlo en un argumento para algo.

2

Creo que la intención es a lo que se refiere bravit.
Los smartypants seguimiento de las cartas-de-la-ley solución es vinculante g con un case;)

+2

Otra solución de Smartypants sería hacer 'g' una función de nivel superior, ya que no se cierra sobre nada de' f' :) – hammar

2

Para ampliar las sugerencias de hammar y bravit, su solución va a requerir no solo una lambda, sino dos, una de las cuales se verá mucho como g, y la otra se verá como la segunda la mitad de f

1

Usando cálculo lambda es g(\x -> 2*x^2 + 10*x + 1)

Así que hay que sustituir g con eso en f x y z = x^3 - g (x + g (y - g z) + g (z^2))

$> echo "f x y z = x^3 - g (x + g (y - g z) + g (z^2))" | sed -r -e 's/g/(\\x -> 2*x^2 + 10*x + 1)/g' 
f x y z = x^3 - (\x -> 2*x^2 + 10*x + 1) (x + (\x -> 2*x^2 + 10*x + 1) (y - (\x -> 2*x^2 + 10*x + 1) z) + (\x -> 2*x^2 + 10*x + 1) (z^2)) 

estoy Es una broma, lo siento.

+3

Estoy seguro de que sus instructores no estarían tan entusiasmados con esa respuesta;) – Nate

+1

Esta es exactamente la respuesta que daría. Hasta donde yo sé, la pregunta se reduce a "aquí, toma este código idiomático y empeora las cosas, solo para demostrar que sabes X". Si el maestro quiere verificar si sé X, deberían plantear una pregunta donde X es realmente útil/necesario. –

-1

Esa pregunta me parece curiosa e interesante. Por lo tanto, estoy tratando de averiguar qué es el cálculo lambda, encontrar una respuesta y quiero mostrarlo a OP (todas las pistas ya se han mostrado en realidad, alerta de spoiler).

En primer lugar, vamos a tratar de redefinir f:

λ> let f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2))) 
f :: 
    (Integer -> Integer) -> Integer -> Integer -> Integer -> Integer 

función Por lo tanto, tenemos que conseguir los números de función y 3 y devolver la respuesta. Usando curring podemos añadir g definición aquí, al igual que f_new = f g:

λ> let f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2))) (\x -> 2*x^2 + 10*x + 1) 
f :: Integer -> Integer -> Integer -> Integer 

Hemos terminado. Vamos a comprobarlo:

λ> f 0 0 0 
-13 

La respuesta es correcta.

UPD:

En esos ejemplos let es sólo una forma de declarar la función en el intérprete, de modo respuesta final es:.

f :: Num a => a -> a -> a -> a 
f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2))) (\x -> 2*x^2 + 10*x + 1)