SML pair tuples conversion - sml

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.

Related

Patterns not matched: Haskell

I wrote a function that takes a list as an input and outputs the sum of its elements, but I get the following error: "Pattern match(es) are non-exhaustive
In an equation for ‘addfunc’: Patterns not matched: []"
Here is my code:
addfunc :: [Int] -> Int
addfunc(x:xs) = x + addfunc xs
When pattern matching, you have to list out all possible cases, so that your program knows what to do for every possible input. Here, the possible input is all lists of integers, which also includes an empty list (a list of zero integers). Your function knows what to do when the input has a first element and other elements; but if it should receive an empty list (which cannot be decomposed into the first element and the other elements), it would not know what to do.
To correct it, simply provide the matching rules for the missing case(s), e.g.
addfunc [] = 0

Combining elements of a sublist of a list

I have the following list of sublists
[[1;5;10];
[2;6;11];
[3;7;12]];
I am trying to a create the following list of sublists:
[[1;2;3];
[5;6;7];
[10;11;12]]
The first sublist of the result should containt the first element of each original sublist, second result sublist should contian the second elements of each of the original sublists and so on.
Each sublist contains the same number of elements as the other sublists. The amount of sublists is at least 2.
I was thinking of using List.map but I am not sure what function to apply to each sublist to exctract the needed elements.
This is what I have so far:
let rec compute list =
List.map (fun x -> ) list
Any suggestions are appreciated!
Here you need two recursions (as you would need 2 imbricated loops in an imperative language).
The first recursion should allow you to go through the inputs line, say from 1 to 3, and at each step of this recursion, you will need a second recursion,to go along the full row.
You can either do it all by hand or you can use List.fold_left. (I would use fold for the inner recursion.

find last element of a list in haskell

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.

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.

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