Spec-Zone.ru › OCaml 4.14

10.23 Операторы связывания

  • 10.23.1 Короткая запись для связывания переменных (let-punning)
  • 10.23.2 Обоснование

(Введено в версии 4.08.0)

let-operator ::=
∣ let (core-operator-char ∣ <) { dot-operator-char }
and-operator ::=
∣ and (core-operator-char ∣ <) { dot-operator-char }
operator-name ::= ...
∣ let-operator
∣ and-operator
letop-binding ::= pattern = expr
∣ value-name
expr ::= ...
∣ let-operator letop-binding { and-operator letop-binding } in expr

Пользователи могут определять операторы let:

let ( let* ) o f =
  match o with
  | None -> None
  | Some x -> f x

let return x = Some x

val ( let* ) : 'a option -> ('a -> 'b option) -> 'b option = 
val return : 'a -> 'a option = 

и затем применять их с помощью удобной синтаксической конструкции:

let find_and_sum tbl k1 k2 =
  let* x1 = Hashtbl.find_opt tbl k1 in
  let* x2 = Hashtbl.find_opt tbl k2 in
    return (x1 + x2)

val find_and_sum : ('a, int) Hashtbl.t -> 'a -> 'a -> int option = 

что эквивалентно расширенной форме:

let find_and_sum tbl k1 k2 =
  ( let* ) (Hashtbl.find_opt tbl k1)
    (fun x1 ->
       ( let* ) (Hashtbl.find_opt tbl k2)
         (fun x2 -> return (x1 + x2)))

val find_and_sum : ('a, int) Hashtbl.t -> 'a -> 'a -> int option = 

Пользователи также могут определять операторы and:

module ZipSeq = struct

  type 'a t = 'a Seq.t

  open Seq

  let rec return x =
    fun () -> Cons(x, return x)

  let rec prod a b =
    fun () ->
      match a (), b () with
      | Nil, _ | _, Nil -> Nil
      | Cons(x, a), Cons(y, b) -> Cons((x, y), prod a b)

  let ( let+ ) f s = map s f
  let ( and+ ) a b = prod a b

end

module ZipSeq :
  sig
    type 'a t = 'a Seq.t
    val return : 'a -> 'a Seq.t
    val prod : 'a Seq.t -> 'b Seq.t -> ('a * 'b) Seq.t
    val ( let+ ) : 'a Seq.t -> ('a -> 'b) -> 'b Seq.t
    val ( and+ ) : 'a Seq.t -> 'b Seq.t -> ('a * 'b) Seq.t
  end

для поддержки синтаксиса:

open ZipSeq
let sum3 z1 z2 z3 =
  let+ x1 = z1
  and+ x2 = z2
  and+ x3 = z3 in
    x1 + x2 + x3

val sum3 : int Seq.t -> int Seq.t -> int Seq.t -> int Seq.t = 

что эквивалентно расширенной форме:

open ZipSeq
let sum3 z1 z2 z3 =
  ( let+ ) (( and+ ) (( and+ ) z1 z2) z3)
    (fun ((x1, x2), x3) -> x1 + x2 + x3)

val sum3 : int Seq.t -> int Seq.t -> int Seq.t -> int Seq.t = 

10.23.1 Короткая запись для связывания переменных (let-punning)

(Введено в версии 4.13.0)

Когда выражение, которое связывается, является переменной, удобно использовать сокращённую запись let+ x in ..., которая расширяется до let+ x = x in .... Эта запись, также известная как let-punning, позволяет сокращённо записать функцию sum3 выше, как:

open ZipSeq
let sum3 z1 z2 z3 =
  let+ z1 and+ z2 and+ z3 in
  z1 + z2 + z3

val sum3 : int Seq.t -> int Seq.t -> int Seq.t -> int Seq.t = 

Этот способ записи также поддерживается для узлов расширения, преобразуя let%foo x in ... в let%foo x = x in .... Однако, чтобы избежать путаницы, такая запись не поддерживается для обычных связываний let.

10.23.2 Обоснование

Это расширение призвано предоставить удобный синтаксис для работы с монадами и аппликативами.

Аппликатив должен предоставить модуль, реализующий следующий интерфейс:

module type Applicative_syntax = sig
  type 'a t
  val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t
  val ( and+ ): 'a t -> 'b t -> ('a * 'b) t
end

где (let+) связано с операцией map, а (and+) — с операцией монойдного произведения.

Монада должна предоставить модуль, реализующий следующий интерфейс:

module type Monad_syntax = sig
  include Applicative_syntax
  val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t
  val ( and* ): 'a t -> 'b t -> ('a * 'b) t
end

где (let*) связано с операцией bind, а (and*) также связано с операцией монойдного произведения.

© 1995-2022 INRIA.
https://v2.ocaml.org/releases/4.14/htmlman/bindingops.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API