2012-06-13 18 views
8

Come si esegue questo haskell in F # in modo pulito?F # versione di corrispondenza del modello haskell

add 1 2 x = 3 + x 
add 1 x y = 1 + x + y 
add z x y = z + x + y 
+0

Non so haskell, qual è l'obiettivo qui? Sembra un'ottimizzazione che il compilatore catturerebbe e risolverebbe. Penso che cercare di scrivere un equivalente in F # con la corrispondenza dei pattern sia più lento. Cosa stai cercando di ottenere? – gjvdkamp

+2

gjvdkamp, ​​non è un ottimizzazione, è un dispositivo sintattico che rende ogni caso più facile da leggere. 'f 1 = x; f 2 = y' è tradotto in 'f a = caso a di 1 -> x; 2 -> y' - http://www.haskell.org/onlinereport/decls.html#sect4.4.3.1 –

risposta

21

Non si può sovraccaricare la funzione stessa, ma è possibile utilizzare il pattern matching direttamente:

let add z x y =    // curried multiple parameters 
    match z, x, y with  // convert to three-tuple to match on 
    | 1, 2, x -> 3 + x 
    | 1, x, y -> 1 + x + y 
    | z, x, y -> z + x + y 

Usage è come previsto: add 1 2 3

Se siete disposti a usare tuple come argomenti (vale a dire rinunciare al curriculum e applicazione parziale), si può anche scrivere in modo più stenografico:

let add =      // expect three-tuple as first (and only) parameter 
    function     // use that one value directly to match on 
    | 1, 2, x -> 3 + x 
    | 1, x, y -> 1 + x + y 
    | z, x, y -> z + x + y 

Usage ora è: add (1, 2, 3)

+0

Grazie! Cercavo gli esempi di corrispondenza del modello f # dappertutto e nessuno corrispondeva a più di un parametro nei campioni, mi è stato dato l'impressione che non si potesse fare questo. –

+0

@Jimmy: Tecnicamente una singola tupla viene abbinata qui, quindi non hai sbagliato ... – ildjarn

+0

@ildjarn: solo nel secondo esempio che non è quello che userei perché si perde il currying/applicazione parziale che ritengo sia una delle parti più vantaggiose di queste lingue –

8

Ricordiamo in Haskell che il general form of functions come una lista di dichiarazioni con i modelli:

f pat1 ... = e1 
f pat2 ... = e2 
f pat3 ... = e3 

è solo zucchero per l'analisi case:

f x1 .. xn = case (x1, .. xn) of 
       (pat1, ..., patn) -> e1 
       (pat2, ..., patn) -> e2 
       (pat3, ..., patn) -> e3 

così la stessa traduzione può essere fatta ad altre lingue con pattern matching ma senza pattern a livello di dichiarazione.

+0

Mi rendo conto che è solo un caso, ma il motivo per cui lo zucchero esiste in haskell è per la pulizia, speravo che qualcosa di simile esistesse in f #, e come ha sottolineato yamen, la corrispondenza in f # può funzionare allo stesso modo –

5

Questo è puramente sintattico. Linguaggi come Haskell, Standard ML e Mathematica consentono di scrivere fuori diversi casi partita come se fossero diverse funzioni:

factorial 0 = 1 
factorial 1 = 1 
factorial n = n * factorial(n-1) 

mentre linguaggi come OCaml e F # richiedono di avere una sola definizione di funzione e utilizzare match o equivalente in il suo corpo:

let factorial = function 
    | 0 -> 1 
    | 1 -> 1 
    | n -> n * factorial(n-1) 

si noti che non c'è bisogno di copiare il nome della funzione più e più volte con questa sintassi e si può scomporre i casi di corrispondenza più facilmente:

let factorial = function 
    | 0 | 1 -> 1 
    | n -> n * factorial(n-1) 

Come scrisse Yamen, fare curriculum con let f a b = match a, b with ... in F #.

Nel classico implementazione albero rosso-nero, trovo la duplicazione dei nomi delle funzioni e poi sul lato destro in standard ML e Haskell abbastanza brutto:

balance :: RB a -> a -> RB a -> RB a 
balance (T R a x b) y (T R c z d) = T R (T B a x b) y (T B c z d) 
balance (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d) 
balance (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d) 
balance a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d) 
balance a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d) 
balance a x b = T B a x b 

rispetto all'equivalente OCaml o F #:

let balance = function 
    | B, z, (T(R, y, T(R, x, a, b), c) | T(R, x, a, T(R, y, b, c))), d 
    | B, x, a, (T(R, z, T(R, y, b, c), d) | T(R, y, b, T(R, z, c, d))) -> 
     T(R, y, T(B, x, a, b), T(B, z, c, d)) 
    | a, b, c, d -> T(a, b, c, d) 
Problemi correlati