Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ocaml pattern matching for "square" tuple?

In attempting to learn Ocaml and functional languages in general, I have been looking into pattern matching. I was reading this documentation, and decided to try the following exercise for myself:

Make an expression that evaluates to true when an integer 4-tuple is input such that each element in the 4-tuple is equal.

(4, 4, 4, 4) -> true

(4, 2, 4, 4) -> false

I find that doing pattern matching for the specificity of the value of the elements to not be obvious. This is the code I wrote.

let sqr x = match x with 
   (a, a, a, a) -> true 
 | (_, _, _, _) -> false ;;

Of course, this code throws the following error:

Error: Variable a is bound several times in this matching

How else can I not only enforce that x is a 4-tuple, but also of strictly integers that are equal?

(Also, of course a "square" tuple should not allow non-positive integers, but I'm more concerned with the aforementioned problem as of now). `

like image 999
Tazzure Avatar asked Dec 24 '17 01:12

Tazzure


People also ask

How does pattern matching work 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.

Can you have a tuple of functions in OCaml?

Every function in OCaml takes exactly one value and returns exactly one result. For instance, our squareRoot function takes one float value and returns one float value. The advantage of always taking one argument and returning one result is that the language is extremely uniform.

How do you write a tuple in OCaml?

To write down an n-tuple, we write the n values in order between parentheses and separated by commas. Any tuple that has a different number of values inside will have a different type than any other tuple, and these types are not compatible.


2 Answers

As you found out, unlike some other languages' pattern-matching systems, you can't do this in OCaml. What you can do is match each element of the tuple separately while using guards to only succeed if some property (like equivalence) holds across them:

let sqr x =
  match x with
  | (a, b, c, d) when a = b && b = c && c = d -> `Equal
  | (a, b, c, d) when (a < b && b < c && c < d)
                   || (a > b && b > c && c > d) -> `Ordered
  | _ -> `Boring
like image 111
Julian Fondren Avatar answered Nov 03 '22 00:11

Julian Fondren


You have many ways to do pattern-matching, pattern matching is not only when using the match keyword

let fourtuple_equals (a,b,c,d) = List.for_all ((=) a) [b;c;d]
val fourtuple_equals : 'a * 'a * 'a * 'a -> bool = <fun>

Here you have a pattern matching directly in the parameter in order to access your four elements tuple.

In this example I use a list to have a more concise code, but is not the more efficient.

like image 35
Aldrik Avatar answered Nov 02 '22 23:11

Aldrik