Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is Haskell sensitive to order in a function definition?

Tags:

haskell

I was trying out the Haskell 99 problems and my first attempt was this one .Although the solution may be a little incorrect ,I just want to know why Haskell throws a warning for the first one and outputs the wrong result

> let { mylast (x:xs) = mylast xs; mylast [] = 0 ;mylast [x] = x;}
Pattern match(es) are overlapped

> mylast [1,2,3,58,8,6,1,231,10]
> 0

but the code below executes just fine.

> let { mylast [] = 0 ;mylast [x] = x;mylast (x:xs) = mylast xs;}
> mylast [1,2,3,58,8,6,1,231,10]
> 10
like image 443
Ramkumar Avatar asked Apr 30 '15 07:04

Ramkumar


People also ask

How do you define a function in Haskell?

The most basic way of defining a function in Haskell is to ``declare'' what it does. For example, we can write: double :: Int -> Int double n = 2*n. Here, the first line specifies the type of the function and the second line tells us how the output of double depends on its input.

Does Haskell evaluate left to right?

The evaluation strategy of Haskell is called “lazy evaluation”. This means it only evaluates arguments of functions when they are needed and from left to right – this is called an “outermost leftmost” evaluation or a “by need” evaluation strategy – and, in addition, it “shares” evaluations of subexpressions.

What does -> mean in Haskell?

(->) is often called the "function arrow" or "function type constructor", and while it does have some special syntax, there's not that much special about it. It's essentially an infix type operator. Give it two types, and it gives you the type of functions between those types.

What does ++ do Haskell?

The ++ operator is the list concatenation operator which takes two lists as operands and "combines" them into a single list.


2 Answers

Yes, the patterns in a function definition are tried in the specified order, and (only) the first matching line is used.

So in your definition

mylast (x:xs) = mylast xs
mylast [] = 0
mylast [x] = x

(reformatted for clarity), a non-empty-list will always be handled by the first line, even the list [x] (with x=x and xs=[]). So your calculation of mylast will happily ignore every element in the list, and finally look at [], hence returning 0.

like image 103
Joachim Breitner Avatar answered Nov 24 '22 02:11

Joachim Breitner


...in other words, Haskell doesn't consider which of two matches is more general and then use the more specific one first. It just considers “does it match or doesn't it?”

In some cases it wouldn't be possible to say which of two matches is more specific. For instance,

foo :: Int -> Int -> Int
foo 0 _ = 0
foo _ 1 = 1
foo n m = foo (m-1) n

If Haskell was supposed to pick the most specific matching pattern, then what result should foo 0 1 yield?

You need to have some arbitrary tie-breaker for such functions, and in Haskell that's simply the order: always match the upper clause first.

like image 29
leftaroundabout Avatar answered Nov 24 '22 02:11

leftaroundabout