Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern-matching in Haskell and Erlang

I have a small Erlang function that compares if two lists are equal:

myEq([], [])         -> true;
myEq([X|Xs], [X|Ys]) -> myEq(Xs, Ys);
myEq(_, _)           -> false.

The comparison takes place on line 2, the X of [X|Xs] always binds to the first element of the first list, the [X|Ys] matches only if the first elements of both lists are equal.

If I try this in Haskell I get an error message: "Conflicting definitions for x". A possible solution in Haskell would be:

myEq (x:xs) (y:ys) = if x == y then myEq xs ys else False

But I would like to know if it is possible to do this in Haskell using pattern matching?

like image 819
Ralli Avatar asked Feb 20 '17 11:02

Ralli


2 Answers

No, in Haskell you cannot use the same variable x in the head of a clause. Haskell does not do unification or equality checks like for instance respectively Prolog and Erlang do. This is specified in the Haskell '98 report:

The set of patterns corresponding to each match must be linear---no variable is allowed to appear more than once in the entire set.

(copied, boldface added)

The only way to do it is using a guard (or any other type of checking in the body of course). You can however write it more elegant like:

myEq [] [] = True
myEq (x:xs) (y:ys) | x == y = myEq xs ys
--                 | otherwise = False
myEq _ _ = False

the otherwise case can be omitted since Haskell will fallback on the last clause and thus return False.

Or perhaps even more elegant:

myEq [] [] = True
myEq (x:xs) (y:ys) = x == y && myEq xs ys
myEq _ _ = False

Personally I think that is better since here you state explicitly that x is equal to y so making mistakes like by accident writing the same variable cannot happen. Although of course it is a matter of taste.

like image 147
Willem Van Onsem Avatar answered Oct 19 '22 17:10

Willem Van Onsem


No. Every variable can be bound at most once on the pattern matching side. If you wanted to bind a variable twice you would have to evaluate to perform unification.

like image 38
jakubdaniel Avatar answered Oct 19 '22 17:10

jakubdaniel