find last element of a list in haskell - list

I wrote the following code to find the last element of a list in haskell:
myLast (x:xs) = do
ret <- if xs == [] then x else (myLast xs)
return ret
The idea is to traverse the list until we are at an element which has the empty list as its next element. When we find it we set ret to that element.
It makes sense for me but when I run the code inside the interactive shell I get the following error:
<interactive>:1:1: error:
• No instance for (Num (m0 b0)) arising from a use of ‘it’
• In a stmt of an interactive GHCi command: print it
edit 1
The reason I used do was because I saw that pattern being used somewhere to also traverse a list, so I thought I could do the same here. I'am avoiding libraries for now to get comfortable with the language.
I wrote the function avoiding the do keyword and now it works:
myLast(x:xs) = if xs == [] then x else (myLast xs)
There's now just an issue with the empty list case. How to approach this in haskell?

let's start with the signature of your function
myLast :: [a] -> a
now, for an empty list input, what can be expected as the output? How you can make up an instance of an arbitrary type a?
Alternatively, you can defer the handling of missing last element to the callers of your function.
myLast :: [a] -> Maybe a

You want
myLast (x:xs) =
to be equal to
if xs == [] then x else (myLast xs)
Great, xs == [], so let's just put it back in:
myLast (x:[]) = x
but what about the else part? Well, let's add another equation for that,
myLast (_:xs) = myLast xs
and we're golden.
What if we call it with an empty list [] though? No definition case will match, and we will get some kind of a run-time error. Well, same thing happens with the built-in function last too, so we're no better and no worse than Haskell itself here.
What is that match that I mentioned, you ask? That's how Haskell functions get invoked. Each function definition can have several clauses, starting with the function's name, and containing a pattern for each expected argument.
In a left hand side of an equation,
(x:[]) is a pattern, matching any singleton list. It can also be written [x]. x will refer to the list's only element, if used in the right-hand side of the equation.
[] is a pattern, matching any empty list.
(x:xs) is a pattern, matching any non-empty list. x will refer to the list's head (i.e. first) element, if used in the right-hand side of the equation; and xs will refer to the rest of the elements in a list (which are also, a list -- also known as its tail).
But wait, you ask. Wouldn't both clauses match for a singleton list, the first for the pattern [x] and the second for (_:xs) with xs matched up with an empty list, []?
Why yes, they both would match indeed; (x:[]) and (_:xs) are not mutually exclusive.
But that's OK, because in Haskell, if the first clause has matched, that's it -- that is the clause that gets executed, and no other attempts at any additional pattern matching and clause selection are made.
That would be Prolog, and that's quite another language.

Related

Match warning and pattern-matching in SML

I was wondering what would be a good strategy to understand if pattern-matching in SML will proceed the Match warning.
Consider the following function:
fun f 7 (x,y) = x * 5.1 | f x (y,#"a") = y;
From first glance, it looks like it does not provide the Match warning. But if I'll run it, it will.
From my point of view, we handle all of the cases. which case we don't handle? even if f 7 (x,#"a") we know which case should be (first one).
My question is, how to decide that the function will output that waning.
Also, I would be glad for an answer why the following function is invalid:
fun f (x::xs) (y::ys) (z::zs) = y::xs::ys::zs;
without zs its valid. how does zs change it?
My question is, how to decide that the function will output that waning.
The compiler has an algorithm that decides this.
Either use the compiler and have it warn you, or use a similar heuristic in your head.
See Warnings for pattern matching by Luc Maranget (2007).
It covers the problem, algorithm and implementation of finding missing and duplicate patterns.
A useful heuristic: Line patterns up, e.g. like:
fun fact 0 = 1
| fact n = n * fact (n - 1)
and ask yourself: Is there any combination of values that is not addressed by exactly one case of the function? Each function case should address some specific, logical category of the input. Since your example isn't a practical example, this approach cannot be used, since there are no logical categories over the input.
And fact is a bit simple, since it's very easy to decide if it belongs to the categories 0 or n.
And yet, is the value ~1 correctly placed in one of these categories?
Here is a practical example of a function with problematic patterns:
fun hammingDistance [] [] = SOME 0
| hammingDistance (x::xs) (y::ys) =
if length xs <> length ys then NONE else
if x = y
then hammingDistance xs ys
else Option.map (fn d => d + 1) (hammingDistance xs ys)
It may seem that there are two logical cases: Either the lists are empty, or they're not:
The input lists are empty, in which case the first body is activated.
The input lists are not empty, in which case they have different or equal length.
If they have different lengths, NONE.
If they have equal lengths, compute the distance.
There's a subtle bug, of course, because the first list can be empty while the second one isn't, and the second list can be empty while the first one isn't. And if this is the case, the second body is never hit, and the distinction between different / equal lengths is never made. Because the task of categorizing is split between pattern matching and if-then-else with precedence to pattern matching.
What I do personally to catch problems like these preemptively is to think like this:
When I'm pattern matching on a list (just for example), I have to cover two constructors (1. [], 2. ::), and when I'm pattern matching on two lists, I have to cover the Cartesian product of its constructors (1. [], [], 2. [], ::, 3. ::, [], and 4. ::, ::).
I can count only two patterns/bodies, and none of them aim to cover more than one of my four cases, so I know that I'm missing some.
If there had been a case with variables, I have to ask how many of my common cases it covers, e.g.
fun hammingDistance (x::xs) (y::ys) =
if x = y
then hammingDistance xs ys
else Option.map (fn d => d + 1) (hammingDistance xs ys)
| hammingDistance [] [] = SOME 0
| hammingDistance _xs _ys = NONE
Here there's only three patterns/bodies, but the last one is a catch-all; _xs and _ys match all possible lists, empty or non-empty, except if they're matched by one of the previous patterns first. So this third case accounts for both of 2. [], :: and 3. ::, [].
So I can't simply count each pattern/body once. Some may account for more than one class of input if they contain very general patterns via pattern variables. And some may account for less of the total input space if they contain overly specific patterns via multiple constructors. E.g.
fun pairs (x::y::rest) = (x, y) :: pairs rest
| pairs [] = []
Here x::y::rest is so specific that I'm not covering the case of exactly one element.

SML: non-constructor applied to argument in pattern #

Why I can't do the following and what are the ways to do it?
datatype boolexp = zero
| one
| compl of boolexp;
fun convert (#"1"::nil) = one
| convert (#"0"::nil) = zero
| convert (#"-":: #"(" :: xs # [#")"]) = compl (convert xs)
It gives me the errors:
non-constructor applied to argument in pattern: #
unbound variable or constructor: xs
The problem is in the last case of convert.
# is a function and not a value constructor (like :: and nil), so you cannot pattern-match on it. There is no way to pattern-match on the last element of a general list.
To accomplish what you're trying to do, you can either:
Pattern-match the beginning out, i.e. #"-":: #"(":: xs, and then check if xs ends with a #")" using List.last.
If you need it to be faster than the approach above, you probably would need to use a specialized data structure that allows for faster reading from both ends of a list. This could for instance a double-ended queue. Okasaki has details on these.

SML pair tuples conversion

I've been trying to solve this pair tuples problem where the input is a list of tuples and the output is a tuple of lists where the first element of each tuple is grouped together and similarly with the second (i.e. [(1,2),(3,4),(5,6)] --> ([1,3,5],[2,4,6])).
I've thought of this code but it gives me an error:
fun convert L = foldl (fn ((x,y),(u,v)) => ((u#x),(v#y)) ([],[]) L;
Any suggestions for a fix?
Concatenation (#) takes two lists, but x and y are values, so you need to wrap them with [] to make a single-element list:
fun convert l=foldl (fn((x,y),(u,v))=>(u#[x],v#[y])) (nil,nil) l
You can use cons instead of concatenation, though the lists inside the returned tuple are reversed:
fun convert l=foldl (fn((x,y),(u,v))=>(x::u,y::v)) (nil,nil) l
# concatenates lists (and x and y are not lists).
Try (u#[x],v#[y]).
Note, however, that appending is a linear-time operation, while prepending (i.e. x::u) is constant. As Alex pointed out, this will build your lists in reverse, but you can resolve this by processing your input in reverse as well - i.e., by using foldr instead of foldl.

Findig the 2nd last item in the list, please explain this solution

// But pattern matching also makes it easy.
def penultimateRecursive[A](ls: List[A]): A = ls match {
case h :: _ :: Nil => h
case _ :: tail => penultimateRecursive(tail)
case _ => throw new NoSuchElementException
}
Can someone comment what this is doing line by line?
Is the [A] a generic like in c# we would do ?
h doesn't seem to be defined?
I think the major part of the algo is the recursive call:
case _ :: tail => penultimateRecursive(tail)
There doesnt' seem to be a check for 2 items in the list, and then taking the 1st item to get the 2nd last, confused!
The keys to understanding the pattern match are to realize that x :: y will only match a list with a single item x followed by the rest of the list y (which could be just Nil, or could be many elements), and that _ means "there needs to be something here, but we won't bother naming it". (And that the matches occur in order, and that lists end with Nil.)
You're correct that [A] is a generic type.
So, the first line:
case h :: _ :: Nil => h
says, if our list looks like (conceptually) Node(h) -> Node(whatever) -> Nil, then we return h. This is exactly a two-element list with the first item selected. Note that Nil does not match any arbitrary tail of the list; it matches only the end-of-list item Nil. This is because of a rule that Scala uses to distinguish the two: lower case variables are treated as wildcards that are to have the appropriate value filled in, while upper case variables are treated as constants to match. (If you must match a lower-case name, you can if surround it by backticks.)
Okay, now suppose it's not a two-element list. Then if it's not empty, it will match
case _ :: tail => penultimateRecursive(tail)
so if we haven't got a two-element list, we throw away the first item and try again. Finally, if we somehow never ended up with a two-element list, we get to
case _ => throw new NoSuchElementException
and we're done. (This could also be case Nil, actually, since this is the only possibility that doesn't match the other two entries.)
A is a type variable, meaning the function is defined generically for any type A.
h is bound by the pattern matching: the first case states, if there are exactly two elements, then call the first h and return it.
There doesnt' seem to be a check for 2 items in the list
There is: h :: _ :: Nil means "an element h, followed by any element, followed by no more elements." Nil isn't an element, it's the end of the list.
and then taking the 1st item to get the 2nd last
Taking the first of a two-element list means taking the penultimate. If the list has fewer or more elements than two, the other two cases apply.
larsmans and Rex have covered your questions, but see Chapter 9 for more details on '::' http://www.scala-lang.org/docu/files/ScalaByExample.pdf
The first line means that any list element h will be returned if h is followed by another one and a Nil pointer (at the end of the list). The actual element following to h is not important, that's why you use _ to specify that there is an element but you don't care about its value.
If the first case does not match, the second case will invoke recursion if the list has a head element and a tail of at least one element.
Lastly you bail out on lists consisting only a single element. Once again, you don't have to care about the actual value of the elements value.

Filtering list of tuples

New to Haskell and have a stumbling block. I'm trying to filter a list of tuples based on the first item.
filter (==(x,_)) lis
I get an illegal '_' error, but I'm not sure how I can get around it?
In Haskell, you cannot iterate over a tuple like you can a list.
If the tuple only has two items, you can use fst to retrieve the first item of the tuple and snd to retrieve the second item.
One way to do what I think you want to do is this approach:
Prelude> let lst = [(1,2), (3,4)]
Prelude> filter ((==1).fst) lst
[(1,2)]
Which only returns the items in the list where the first element is equal to 1; of course, you can substitute x where I put 1.
To be a little more specific, (==1).fst first applies fst to the element in lst, then applies (==1) to the result of fst -- technically, the dot composes the two functions together.
You can't give an argument with a wildcard _ in it to the == operator (or to any other function). The argument needs to be a real value, not a pattern that should be matched against.
If you want to use pattern matching you could use a lambda function as you filter condition:
filter (\(a,_) -> a == x) lis
Also, there is the predefined function fst to extract the first element of a two-element tuple. This can be combined with == to do the same test:
filter ((== x) . fst)) lis