Sök…


Syntax

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

Generiska algoritmer

Funktioner med högre ordning kan användas för att implementera generiska algoritmer, vilket ger upp ansvaret att tillhandahålla slutliga detaljer till användaren. List.sort förväntar sig till exempel en jämförelsefunktion som gör det möjligt att implementera olika sätt att sortera. Här implementerar vi fall-okänslig sortering av strängar:

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

Det finns en rik lista över högre ordningens funktioner i standardbiblioteket, särskilt i List modulen se List.fold_left och List.sort till exempel. Mer avancerade exempel finns i tredjepartsbibliotek. Ett bra exempel är den simulerade glödgningen som implementerats i ocaml-gsl . Simulerad glödgning är en generisk optimeringsprocedur som parametriseras av en funktion som används för att utforska uppsättningen av problemstillstånd och en felfunktion (kallas här energifunktion).

Användare som är bekanta med C ++ kan jämföra detta med strategimönstret .

Kassera systemresurser även när ett undantag tas upp

Funktioner med högre ordning kan användas för att säkerställa att systemresurser avyttras, även om en behandling ger ett undantag. Mönstret som används av with_output_file tillåter en ren åtskillnad av oro: den högre ordningen with_output_file funktionerna tar hand om hanteringen av systemresurserna bundna till filmanipulation medan behandlingen f endast konsumerar utgångskanalen.

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)

Låt oss använda denna högre ordning för att implementera en funktion som skriver en sträng till en fil:

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

Med mer avancerade funktioner än fun c -> output_string cs är det möjligt att spara mer komplexa värden. Se till exempel Marshal- modulen i standardbiblioteket eller Yojson- biblioteket av Martin Jambon.

Sammansättningsoperatörer

Två användbara funktioner med högre ordning är den binära applikationen ( @@ ) och omvänd applikation eller "rör" ( |> ). Även om de är tillgängliga som primitiv sedan 4.01 , kan det fortfarande vara lärorikt att definiera dem här:

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

Tänk på problemet med att öka kvadratet på 3. Ett sätt att uttrycka beräkningen är detta:

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

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

Observera att vi inte bara kunde göra succ square 3 eftersom (på grund av vänsterassociativitet ) som skulle minska till det meningslösa (succ square) 3 . Med hjälp av applikation ( @@ ) kan vi uttrycka det utan parenteser:

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

Lägg märke till hur den sista operationen som ska utföras (nämligen succ ) inträffar först i uttrycket? Operatören för omvänd applikation ( |> ) tillåter oss att, ja, vända detta:

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

Siffran 3 "flyttas" nu genom square och sedan succ , i motsats till att appliceras på square att ge ett resultat som succ appliceras på.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow