Split list of tuples into different partitions in ML

50 Views Asked by At

I've done Python for quite awhile and what I'm trying to achieve should've been identical but I'm running into a pesky error.

My problem is that I would like a list of tuples in ML split into separate variables.

val myList = [(1,2),(3,4)];
val (x :: y) = myList;

In the above statement x would be (1,2) and y would be (3,4), ... [If there was anymore]. Simple enough.

Now I want to introduce a third variable z where z would be (3,4),... and x, y would be (1,2) respectfully.

val myList = [(1,2),(3,4)];
val ((x :: y) :: z) = myList;

The error produced by the previous snippet is:

error: Pattern and expression have incompatible types.
Pattern: ((x :: y) :: z) : 'a list list
   Expression: myList : (int * int) list
   Reason: Can't unify 'a list to int * int (Incompatible types)

Edit: As requested, this is what z should achieve.

val myList = [(1,2),(3,4)];
val ((x :: y) :: z) = myList;

Output would be: x = 1, y = 2, z = (3,4)

In Python this would be:

Python 3.9.6 | packaged by conda-forge | (default, Jul 11 2021, 
03:35:11) 
[Clang 11.1.0 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> (x,y),z = [(1,2),(3,4)]
>>> x
1
>>> y
2
>>> z
(3, 4)
2

There are 2 best solutions below

0
Kyle On

Upon further investigation, :: doesn't denote a comma where as in Python I would've used one. Switching between the two solves this:

val ((x :: y) :: z) = myList;

Now becomes:

val ((x, y), z) = myList;
0
geq0 On

Your first snippet doesn't do what you think it does:

val myList = [(1, 2), (3, 4)];
val (x :: y) = myList;

The pattern x :: y binds x to the head of the list (in this case, (1, 2)), and y to the tail of the list (in this case, [(3, 4)], not (3, 4)). If you want to extract the first two elements, do this:

val myList = [(1, 2), (3, 4)];
val x :: y :: z = myList;

x will be bound to (1, 2), the tail will again be pattern-matched so that y is bound to (3, 4), and z to the empty list [].

To pattern-match the pieces in a pair (2-tuple), use (x, y). The following should achieve what you want:

val myList = [(1, 2), (3, 4)];
val (x, y) :: z :: _ = myList;
(* x: 1
 * y: 2
 * z: (3, 4)
 *)