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
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.
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.
(->) 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.
The ++ operator is the list concatenation operator which takes two lists as operands and "combines" them into a single list.
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
.
...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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With