Szukaj…


Składnia

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

Ogólne algorytmy

Funkcje wyższego rzędu mogą być używane do implementacji ogólnych algorytmów, rezygnując z odpowiedzialności za podanie ostatecznych szczegółów użytkownikowi. Na przykład List.sort oczekuje funkcji porównania, która pozwala zaimplementować różne sposoby sortowania. W tym przypadku implementujemy sortowanie ciągów bez rozróżniania wielkości liter:

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

W bibliotece standardowej znajduje się bogata lista funkcji wyższego rzędu, zwłaszcza w module List , patrz na przykład List.fold_left i List.sort . Bardziej zaawansowane przykłady można znaleźć w bibliotekach stron trzecich. Dobrym przykładem jest symulowane wyżarzanie zaimplementowane w ocaml-gsl . Symulowane wyżarzanie jest ogólną procedurą optymalizacji, która jest parametryzowana przez funkcję służącą do badania zestawu stanów problemu i funkcję błędu (zwaną tutaj funkcją energii).

Użytkownicy znający C ++ mogą porównać to do wzorca strategii .

Zasoby systemowe należy usuwać nawet po zgłoszeniu wyjątku

Można stosować funkcje wyższego rzędu, aby zapewnić, że zasoby systemowe są usuwane, nawet gdy leczenie stwarza wyjątek. Wzorzec używany przez with_output_file pozwala na czyste rozdzielenie obaw: funkcje wyższego rzędu with_output_file zajmują się zarządzaniem zasobami systemowymi związanymi z manipulowaniem plikami, podczas gdy leczenie f zajmuje tylko kanał wyjściowy.

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)

Użyjmy tej funkcji wyższego rzędu, aby zaimplementować funkcję zapisującą ciąg znaków do pliku:

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

Używając bardziej zaawansowanych funkcji niż fun c -> output_string cs można zapisać bardziej złożone wartości. Zobacz na przykład moduł Marshal w bibliotece standardowej lub bibliotekę Yojson autorstwa Martina Jambona.

Operatorzy składu

Dwie przydatne funkcje wyższego rzędu to aplikacja binarna ( @@ ) i operatory odwrotnej aplikacji lub „potok” ( |> ). Chociaż od 4.01 są dostępne jako prymitywy, zdefiniowanie ich tutaj może być pouczające:

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

Zastanów się nad zwiększeniem kwadratu o 3. Jednym ze sposobów wyrażenia tego obliczenia jest:

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

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

Zauważ, że nie mogliśmy po prostu zrobić succ square 3 ponieważ (ze względu na lewostronne skojarzenie ) zredukowałoby to do bez znaczenia (succ square) 3 . Za pomocą aplikacji ( @@ ) możemy wyrazić to bez nawiasów:

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

Zauważ, jak ostatnia operacja, którą należy wykonać (a mianowicie succ ), pojawia się jako pierwsza w wyrażeniu? Operator odwrotnej aplikacji ( |> ) pozwala nam odwrócić to:

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

Liczba 3 jest teraz „ succ ” przez square a następnie succ , w przeciwieństwie do nakładania na square celu uzyskania wyniku, na który stosuje się succ .



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow