Ricerca…


Sintassi

  • val (|>) : 'a -> ('a -> 'b) -> 'b
  • val (@@) : ('a -> 'b) -> 'a -> 'b

Algoritmi generici

Le funzioni di ordine superiore possono essere utilizzate per implementare algoritmi generici, rinunciando alla responsabilità di fornire dettagli finali all'utente. Ad esempio, List.sort aspetta una funzione di confronto, che consente di implementare vari modi di ordinamento. Qui implementiamo l'ordinamento case-insensitive di stringhe:

let string_case_insensitive_sort lst =
  let case_insensitive_compare a b =
    String.compare (String.lowercase a) (String.lowercase b)
  in
  List.sort case_insensitive_compare lst

C'è una ricca lista di funzioni di ordine superiore nella libreria standard, specialmente nel modulo Elenco , vedere List.fold_left e List.sort per esempio. Esempi più avanzati possono essere trovati in librerie di terze parti. Un buon esempio è la ricottura simulata implementata in ocaml-gsl . La ricottura simulata è una procedura di ottimizzazione generica parametrizzata da una funzione utilizzata per esplorare l'insieme degli stati del problema e una funzione di errore (chiamata qui funzione energetica).

Gli utenti che hanno familiarità con C ++ possono confrontarlo con il modello di strategia .

Disponi le risorse di sistema anche quando viene sollevata un'eccezione

Le funzioni di ordine superiore possono essere utilizzate per garantire che le risorse di sistema vengano smaltite, anche quando un trattamento solleva un'eccezione. Il pattern utilizzato da with_output_file consente una with_output_file separazione dei problemi: le funzioni con with_output_file ordine with_output_file si occupano della gestione delle risorse di sistema legate alla manipolazione dei file mentre il trattamento f consuma solo il canale di output.

let with_output_file path f =
  let c = open_out path in
  try
    let answer = f c in
    (close_out c; answer)
  with exn -> (close_out c; raise exn)

Usiamo questa funzione di ordine superiore per implementare una funzione scrivendo una stringa in un file:

let save_string path s =
  (with_output_file path) (fun c -> output_string c s)

Usando funzioni più avanzate di quelle fun c -> output_string cs è possibile salvare valori più complessi. Si veda ad esempio il modulo Marshal nella libreria standard o la libreria Yojson di Martin Jambon.

Operatori di composizione

Due utili funzioni di ordine superiore sono gli operatori di applicazioni binarie ( @@ ) e di applicazione inversa o "pipe" ( |> ). Sebbene dal 4.01 siano disponibili come primitive, potrebbe essere comunque istruttivo definirli qui:

let (|>) x f = f x
let (@@) f x = f x

Considera il problema di incrementare il quadrato di 3. Un modo per esprimere questo calcolo è questo:

(* 1 -- Using parentheses *)
succ (square 3)
(* - : int = 10 *)

(* where `square` is defined as: *)
let square x = x * x

Si noti che non potremmo semplicemente fare succ square 3 perché (a causa di associatività di sinistra ) che si ridurrebbe al senza significato (succ square) 3 . Usando l'applicazione ( @@ ) possiamo esprimere quello senza le parentesi:

(* 2 -- Using the application operator *)
succ @@ square 3
(* - : int = 10 *)

Si noti come l'ultima operazione da eseguire (vale a dire succ ) si verifica prima nell'espressione? L'operatore di reverse-applicazione ( |> ) ci consente di, invertire, questo:

(* 3 -- Using the reverse-application operator *)
3 |> square |> succ
(* - : int = 10 *)

Il numero 3 viene ora "convogliato" attraverso il square e quindi succ , anziché essere applicato al square per ottenere un risultato a cui viene applicato succ .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow