2011-11-19 15 views
7

dovrei prendere questo codice:Riusare una funzione lambda in 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 

e riscrivere senza dove (o lasciare).

significano per scriverlo con una funzione lambda (\ x -> ...)

Sto cercando di riutilizzare una funzione lambda su Haskell. Qualche idea?

+6

'f = capovolgere capovolgere ((1 +) ap ((+). (2 *). (^ 2)) (10 *)). (Flip .) . ap ((.). (.). (.). (-). (^ 3)) ((ap id.).). flip flip (flip id. (^ 2)). (liftM2 (liftM2 (() id). (.). (.). (+)) ': f fatto senza senso da lambdabot – fuz

risposta

12

Come suggerimenti bravit in, è possibile riscrivere un non-ricorsiva let utilizzando un lambda nel seguente modo:

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

dove x è una variabile e A e B sono espressioni.

+5

La cosa che trovo divertente in questo trucco è che in realtà è una pratica standard in Javascript poiché solo le funzioni possono introdurre un blocco di scope lì. – hugomg

+1

Non sono ancora sicuro di capire come è possibile riutilizzarlo – Asaf

+0

@Asaf: è possibile fare riferimento a 'x' più volte in' B'. Ad esempio, prendi '(\ x -> x + x) 3'. Questo è equivalente a '3 + 3', eccetto che devi solo scrivere il' 3' una volta. – hammar

8

Per riutilizzare qualcosa è possibile renderlo un argomento per qualcosa.

2

Penso che l'intenzione sia ciò a cui ci si riferisce.
I smartypants seguire-le-lettere-of-the-legge soluzione è vincolante g con un case;)

+2

Un'altra soluzione di smartypants sarebbe quella di rendere 'g' una funzione di primo livello, dal momento che non chiude nulla da' f' :) – hammar

2

Per espandere i suggerimenti di hammar e bravit, la tua soluzione richiederà non solo un lambda, ma due, uno dei quali avrà un aspetto molto simile a g, e l'altro sarà molto simile al secondo la metà di f

1

Utilizzando lambda calcolo g è (\x -> 2*x^2 + 10*x + 1)

quindi è necessario sostituire g con questo in 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)) 

sono sto scherzando, scusa.

+3

Sono sicuro che i suoi istruttori non sarebbero entusiasti di quella risposta;) – Nate

+1

Questa è esattamente la risposta che darei. Per quanto ne so, la domanda si riduce a "qui, prendi questo codice idiomatico e fallo peggiorare, solo per dimostrare che conosci X". Se l'insegnante vuole verificare se conosco X, dovrebbe porre una domanda dove X è effettivamente utile/necessario. –

-1

Questa domanda mi sembra un po 'curiosa e interessante. Quindi, sto cercando di capire qual è il calcolo lambda, trovare una risposta e voglio mostrarlo a OP (tutti gli hint sono già stati effettivamente mostrati, avviso spoiler).

In primo luogo, proviamo a ridefinire 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 

funzione Così, abbiamo, che ottiene i numeri funzione e 3 e restituire la risposta. Utilizzando curring possiamo aggiungere g definizione proprio qui, come 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 

Abbiamo finito. Controlliamo:

λ> f 0 0 0 
-13 

La risposta è corretta.

UPD:

In tali esempi let è solo un modo per dichiarare funzione nell'interprete, quindi risposta finale è:.

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)