Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OCaml equivalent to Haskell's @ in pattern matching (a.k.a. as-pattern)

In Haskell, while pattern matching, I can use @ to get the entire structure in a pattern. (For easier Googling, this structure is known as an as-pattern.)

For example, x:xs decomposes a list into a head and a tail; I can also get the entire list with xxs@(x:xs).

Does OCaml have something like this?

like image 768
APerson Avatar asked Nov 08 '17 13:11

APerson


People also ask

What is pattern matching in OCaml?

Pattern matching comes up in several places in OCaml: as a powerful control structure combining a multi-armed conditional, unification, data destructuring and variable binding; as a shortcut way of defining functions by case analysis; and as a way of handling exceptions.

Is OCaml or Haskell?

If Haskell is a niche language, then OCaml is a super-niche language. The OCaml community is much smaller. Where Haskell is doing more-or-less fine with libraries, OCaml has significantly less to propose. There are some nice libraries in OCaml, but in many areas the situation is not perfect.


2 Answers

You can use as:

let f = function
| [] -> (* ... *)
| (x::xs) as l ->
  (*
   here:
   - x is the head
   - xs is the tail
   - l is the whole list
  *)
like image 167
Étienne Millon Avatar answered Oct 27 '22 23:10

Étienne Millon


Let me extend Etienne's answer a little bit with some examples:

let x :: xs as list = [1;2;3];;
val x : int = 1
val xs : int list = [2; 3]
val list : int list = [1; 2; 3]

When you write <pattern> as <name>, the variable <name> is bound to the whole pattern on the left, in other words, the scope of as extends as far to the left as possible (speaking more techically as has lower priority than constructors, i.e., the constructors bind tighter). So, in case of the deep pattern matching, you might need to use parentheses to limit the scope, e.g.,

let [x;y] as fst :: ([z] as snd) :: xs as list = [[1;2];[3]; [4]];;
val x : int = 1
val y : int = 2
val fst : int list = [1; 2]
val z : int = 3
val snd : int list = [3]
val xs : int list list = [[4]]
val list : int list list = [[1; 2]; [3]; [4]]
like image 35
ivg Avatar answered Oct 28 '22 00:10

ivg