After some time I've decied to back to learning some functional programming. I've decided to pick Haskell this time, because of its features and .. syntax.
At the moment I am doing some exercises and I am stuck. I want to write a function that picks second last element from the list, i.e. given [1,2,3,4] it would 3.
Here's my function.
lastButOne xs
| null xs = xs
| length xs == 1 = xs
| length xs == 2 = lastButOne head xs
| otherwise = lastButOne tail xs
Unfortunately it yields some errors.
Couldn't match expected type `[a]' with actual type `[a1] -> [a1]'
Relevant bindings include
xs :: [a] (bound at lastButOne.hs:1:12)
lastButOne :: [a] -> [a] (bound at lastButOne.hs:1:1)
Probable cause: `tail' is applied to too few arguments
In the first argument of `lastButOne', namely `tail'
In the expression: lastButOne tail xs
I've tried with some parthness, like (head xs) and (tail xs), but it doesn't help.
Occurs check: cannot construct the infinite type: a ~ [a]
Expected type: [[a]]
Actual type: [a]
Relevant bindings include
xs :: [a] (bound at lastButOne.hs:1:12)
lastButOne :: [a] -> [a] (bound at lastButOne.hs:1:1)
In the first argument of `head', namely `xs'
In the first argument of `lastButOne', namely `(head xs)'
Follow-up: Or should I write Follow-up's. Well, my orginal idea was to write a function that yields head element if list length is one. So given the Lee's explanation it's easy to come up with the following:
lastPattern :: [a] -> Maybe a
lastPattern [] = Nothing
lastPattern [x] = Just x
lastPattern [x,_] = Just x
lastPattern (_:xs) = lastPattern xs
Ane here's the first question. What is the pattern for both conditions [x] and [x,_]?
Next thing I wanted to do is to write the same function with the reverse (as pointed out by Paul Johnson). I quickly came up with head (tail (reverse [1,2,3,4])) which seemed to work fine in the REPL. But when I started some coding I end up with
lastRev :: [a] -> a
lastRev xs
| null xs = error "empty list"
| length xs == 1 = error "too short"
| otherwise = head (tail (reverse xs))
since the head function is head :: [a] -> a . The above function is a little mess for my taste, so to say. Is there any way I could make it to be :: [a] -> Maybe a ? That's the second question.
Last but not least - the third question. Which function is better in terms of performance? How can I measure it in Haskell?
(head xs) returns an a and you're trying to pass it to lastButOne which requires a [a] argument. You could just return head xs directly in this case. You also have a problem with the first two cases since they return a list, while an element is required. Since there is no such element in this cases you could return an error:
lastButOne :: [a] -> a
lastButOne xs
| null xs = error "empty list"
| length xs == 1 = error "list too short"
| length xs == 2 = head xs
| otherwise = lastButOne (tail xs)
are more functional solution would be to encode the partiality in the function type and return a Maybe a so you can return Nothing if the input list is too short:
lastButOne :: [a] -> Maybe a
lastButOne xs
| null xs = Nothing
| length xs == 1 = Nothing
| length xs == 2 = Just (head xs)
| otherwise = lastButOne (tail xs)
finally, a better solution would be to use pattern matching instead of guarding on the length:
lastButOne :: [a] -> Maybe a
lastButOne [] = Nothing
lastButOne [_] = Nothing
lastButOne [x,_] = Just x
lastButOne (_:xs) = lastButOne xs
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