2013-05-19 14 views
17

Solo una domanda veloce. Mi chiedo se ci sia un operatore di composizione di funzioni infisso in OCaml definito nella libreria standard (o in Jane Street's Core o in Batterie) come la funzione (.) In Haskell che ci salva parecchie parentesi poiché possiamo scrivere (f . g . h) x invece di il meno attraente f (g (h x))).Esiste un operatore di composizione delle funzioni infisso in OCaml?

Grazie gente.

risposta

18

La risposta è la stessa di flip :-). La composizione delle funzioni non è definita nella libreria standard OCaml. In questo caso, non è qualcosa che mi manca una volta ogni tanto, mi manca tutto il tempo.

Il progetto OCaml Batteries Included definisce la composizione della funzione (nell'ordine specificato) utilizzando l'operatore -| nel modulo BatStd. Come sottolinea lukstafi (vedi sotto), questo operatore apparentemente cambierà in % in una futura versione di Batterie. (L'ho verificato nel loro albero dei sorgenti.)

Per quanto posso vedere, il progetto di Jane Street Core non definisce un operatore di composizione di funzione. Definisce una funzione compose nel modulo Fn.

+1

Grazie tu Jeffrey. Sei stato così utile. Al momento non ho accesso alla documentazione. In seguito alle tue informazioni, ho trovato comunque una funzione 'compose' nel file sorgente di CoreStd.Fn di Jane Street (cf https://github.com/janestreet/core/blob/master/lib/fn. mli, riga 31). Grazie. – tfboy

+0

FYI questo è il loro link tradizionale per i documenti ma è giù: https://ocaml.janestreet.com/ocaml-core/latest/doc/ – rgrinberg

+0

(Grazie, sto aspettando di vedere se ritorna o se forse c'è invece un nuovo collegamento.) –

9

C'è la funzione Fn.compose in Core, ma non è un operatore di infisso. Inoltre, è implementato come una funzione regolare e ha un sovraccarico di runtime.

In pratica, è piuttosto comodo utilizzare l'operatore di condotte. Non ha sovraccarico di runtime come implementato direttamente nel compilatore (a partire da 4.00). Vedi Optimized Pipe Operators per maggiori dettagli.

L'operatore di conduttura è disponibile come '|>' in Core. Quindi, è possibile riscrivere la vostra espressione come segue: h x |> g |> f

+2

Alcune persone pensano che l'operatore pipe singolo '|>' di Core sia una buona scelta perché semplifica il numero di operatori di infissi da ricordare. In teoria, puoi avere composizione di funzioni e operatori di pipe, ciascuno in avanti e indietro, quindi 4 in totale. Ma è davvero d'aiuto? Alcuni lo vedono come eccessivo e preferiscono avere solo '|>'. –

6

Voglio solo aggiungere che l'operatore è abbastanza facile da comprendere, in F # è semplicemente definito come:

let (<<) f g x = f(g(x));; 

che ha la firma di tipo: val (<<) : f:('a -> 'b) -> g:('c -> 'a) -> x:'c -> 'b facendo esattamente quello che ti serve ...

(f << g << h) x = f(g(h(x)) 

in modo non è necessario il progetto batterie se non si dispone di

mi piacerebbe aggiungere che la ragione sembra << è, come si può immaginare, perché l'operatore >> fa il contrario:

let (>>) f g x = g(f(x));; 

(f >> g >> h) x = h(g(f(x)) 
+0

È grandioso. In OCaml, l'operatore '>>' funziona perfettamente. Tuttavia, l'operatore '' 'blocca completamente l'interprete. Perché pensi che sia? –

+1

Ho testato entrambe le definizioni sopra e non vedo alcuna prova per il reclamo. Se vuoi una buona risposta, devi pubblicare una domanda completa con un codice di esempio. –

+1

Sembra un errore di accettazione del token. Ho definito gli operatori come sopra e 'let f = (+) 1' e' let g = (*) 3'. Al REPL, '(f >> g) 10' è' 33'. Tuttavia, '(f << g) 10' a quanto pare non consente all'interprete di elaborare l'input perché il token' '' è cattivo (avevo precedentemente pensato che il REPL fosse appeso ma ho notato l'errore di analisi quando ho provato a compilare da un file). Questo può essere il risultato di << << 'essendo una parola chiave riservata (http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#sec72), ma per qualche motivo' >> 'funziona (per adesso). Sto eseguendo OCaml 4.01.0. –

4

L'uso di un operatore composizione infisso sembra essere scoraggiato. (vedi this discussion).

È possibile scrivere f @@ g @@ h x anziché f (g (h x))).

0

Forse potrebbe aiutarti.

let identite f = f 
let (>>) = List.fold_right identite 

prova:

# let f=fun x-> x+1 and 
     g=fun x-> x*2 and 
     h=fun x-> x+3;; 

# [f;g;h] >> 2;; 
- : int = 11 
1

In Containers (ancora un'altra sostituzione stdlib per O'Caml), l'operatore composizione funzione viene richiamata % e può essere trovato nel modulo CCFun:

open Containers 
open Fun 

let is_zero n = (n = 0) 

let nonzeros = List.filter (not % is_zero) [0;1;2;3;0] 
Problemi correlati