Mi sto appena avviando con F # e vediamo come è possibile utilizzare il currying per precaricare il 1 ° parametro a una funzione. Ma come si farebbe con il 2 °, 3 ° o qualunque altro parametro? Chiamerei i parametri per renderlo più facile? Esistono altri linguaggi funzionali che hanno chiamato parametri o un altro modo per rendere il curriculum indifferente all'ordine dei parametri?Come si curry il parametro 2nd (o 3rd, 4th, ...) in F # o in qualsiasi linguaggio funzionale?
risposta
In genere è sufficiente utilizzare un lambda:
fun x y z -> f x y 42
è una funzione come 'f', ma con il terzo parametro legato a 42.
È inoltre possibile utilizzare combinatori (come qualcuno ha detto "flip di Haskell "in un commento), che riordina gli argomenti, ma a volte lo trovo confuso.
Si noti che la maggior parte delle funzioni al curry vengono scritte in modo che l'argomento più probabile da applicare parzialmente venga prima.
F # ha i parametri con nome per i metodi (non i valori delle funzioni let-bound), ma i nomi si applicano ai parametri 'tupled'. I parametri al curry nominati non hanno molto senso; se ho una a due argomenti funzione curry 'f', mi sarei aspettato che, data
let g = f
let h x y = f x y
poi 'g' o 'h' sarebbe sostituibili per 'f', ma i parametri di 'nome' rendono questo non necessariamente vero. Vale a dire, i "parametri nominati" possono interagire male con altri aspetti del design del linguaggio e personalmente non conosco un buon design per "parametri nominati" che interagiscono bene con i "valori di funzione al curry di prima classe".
OCaml, la lingua su cui è basato F #, ha argomenti etichettati (e facoltativi) che possono essere specificati in qualsiasi ordine e che è possibile applicare parzialmente una funzione in base ai nomi di tali argomenti. Non credo che F # abbia questa caratteristica.
Si potrebbe provare a creare qualcosa come la funzione flip
di Haskell. Creare varianti che saltino ulteriormente l'argomento nella lista degli argomenti non dovrebbe essere troppo difficile.
let flip f a b = f b a
let flip2 f a b c = f b c a
let flip3 f a b c d = f b c d a
F # ha argomenti denominati opzionali, ma sono solo per le definizioni 'member' (non per le definizioni' let'), e non possono essere curried in questo modo (tutti gli argomenti che non specifichi prendono i loro valori predefiniti, e non puoi ometti quelli non opzionali). –
@Pavel: guarda la mia risposta. – ttsiodras
In Python, è possibile utilizzare functools.partial
o una lambda. Python ha nominato argomenti. functools.partial
può essere utilizzato per specificare i primi argomenti posizionali e qualsiasi argomento con nome.
from functools import partial
def foo(a, b, bar=None):
...
f = partial(foo, bar='wzzz') # f(1, 2) ~ foo(1, 2, bar='wzzz')
f2 = partial(foo, 3) # f2(5) ~ foo(3, 5)
f3 = lambda a: foo(a, 7) # f3(9) ~ foo(9, 7)
Solo per completezza - e dal momento che lei ha chiesto informazioni sugli altri linguaggi funzionali - come si farebbe in OCaml, probabilmente la "madre" di F #:
$ ocaml
# let foo ~x ~y = x - y ;;
val foo : x:int -> y:int -> int = <fun>
# foo 5 3;;
- : int = 2
# let bar = foo ~y:3;;
val bar : x:int -> int = <fun>
# bar 5;;
- : int = 2
Quindi, in OCaml si può hardcode qualsiasi parametro chiamato che vuoi, semplicemente usando il suo nome (nell'esempio sopra).
Microsoft ha scelto di non implementare questa funzione, come hai scoperto ... A mio modesto parere, non si tratta di "scarsa interazione con altri aspetti del design del linguaggio" ... è più probabile a causa dello sforzo aggiuntivo ciò richiederebbe (nell'implementazione del linguaggio) e il ritardo che causerebbe nel portare la lingua nel mondo - quando in realtà solo poche persone (a) dovrebbero essere a conoscenza del "stepdown" da OCaml, (b) usano argomenti di funzione denominati Comunque.
io sono in minoranza, e li uso - ma è davvero qualcosa di facilmente emulato in F # con l'associazione di una funzione locale:
let foo x y = x - y
let bar x = foo x 3
bar ...
In Haskell c'è un 'funzione di flip' che inverte l'ordine di parametri di una funzione. Con quello puoi farlo sul secondo parametro. –
E una combinazione di 'flip' e' (.) 'Ti permetterà di estenderlo a qualsiasi parametro. – ephemient