List operation in Haskell - list

I have this list of type ([(Double,Double)],[(Double,Double)]). example list = ([(1.0,1.0), (2.0,1.0), (1.0,1.0), (1.0,3.0)],[(1.0,4.0), (1.0,5.0), (1.0,1.0), (1.0,2.0), (1.0,3.0), (1.0,4.0), (1.0,5.0)])
How would I access all the data after the fourth tuple (1.0, 3.0). I have already tried the tail function but doesn't seem to work. Thanks.

Well, for one, your list isn't a list, but a tuple :)
type MyData = (MyList, MyList)
type MyList = [MyListElem]
type MyListElem = (Double, Double)
Now, accessing the 2nd list is simply snd.
snd :: (a,b) -> b
So in your case:
snd :: MyData -> MyList
Alternatively, using Lens, you can use a lens on that directly:
list ^. _2

It's not a list, but a tuple of lists. In fact, a tuple of lists of tuples.
To get the second part of a tuple, use the snd command:
snd ([(1.0,1.0), (2.0,1.0), (1.0,1.0), (1.0,3.0)],[(1.0,4.0), (1.0,5.0), (1.0,1.0), (1.0,2.0), (1.0,3.0), (1.0,4.0), (1.0,5.0)])
This yields:
[(1.0,4.0),(1.0,5.0),(1.0,1.0),(1.0,2.0),(1.0,3.0),(1.0,4.0),(1.0,5.0)]
From here on, you can continue to get the parts of the second list using tail or the !! operator.
For completeness, the first part of a tuple can be obtained using the fst command.

Related

How to use sml to write a function to turn a list of 2-tuples to a flattened list?

I got a problem that needs to turn a list of tuples into a flattened list for example:
[(1,2), (3,4), (5,6)] can be turned into [1,2,3,4,5,6]
I have tried to write a function like this:
fun helper2(nil,b) = []
| helper2(a,nil) = []
| helper2(a::l1,b::l2) =l1::l2
fun flatten2 [] = []
| flatten2 ((a,b)::tl) = helper2(a,b)
It shows:
val flatten2 = fn : ('a list * 'a list list) list -> 'a list list
And when I tried to run it using command flatten2[(1,2),(3,4),(5,6)];
It will give me the following error message:
stdIn:1.2-1.29 Error: operator and operand do not agree [overload conflict]
operator domain: ('Z list * 'Z list list) list
operand: ([int ty] * [int ty]) list
in expression:
flatten2 ((1,2) :: (3,4) :: (<exp>,<exp>) :: nil)
My questions are:
Why SML see the a and b values as lists, not just simply a and b
How can I revise my code so SML can see a and b as 'a and 'b not lists
How to make this code work the way it should be?
Thanks
First question: As to why the type comes out as ('a list * 'a list list) it's because type inference is looking at this part of the code:
| helper2(a::l1,b::l2) =l1::l2
^^
here
Keep in mind that the type of the "cons" (::) operator is 'a -> 'a list -> 'a list, it is gluing a single element onto a list of that same type of element. So SML has concluded that whatever l1 and l2 are, the relationship is that l2 is a list of whatever l1 is.
fun helper2(nil,b) = []
Says that a must be a list because nil has type 'a list. Therefore, l2 has to be a list of lists (of some type 'a).
Question 2 and 3: I'm not quite sure how to correct the code as it is written. I'd probably write something like this:
fun helper2 [] accum = List.rev accum
| helper2 ((a,b)::tl) accum = helper2 tl (b :: a :: accum);
fun flatten2 list = helper2 list [];
helper2 does all of the dirty work. If the input list is empty then we're all done and we can return the reversed accumulator that we've been building up. The second case is where we actually add things to the accumulator. We pattern match on the head and the tail of the list. This pattern match means that the input has type ('a * 'a) list (a list of tuples where both elements are the same type). In the head, we have a tuple and we name the first and second element a and b, respectively. We prepend a then b onto the accumulator and recursively call helper2 on the tail of the list. Eventually, we'll chew through all the elements in the list and then we'll be left with just the accumulator -- which, recall, has all the elements but in the reverse order. Calling List.rev reverses the accumulator and that's our answer.
And when I load and run it I get this:
- flatten2 [(1,2), (3,4), (5,6)];
val it = [1,2,3,4,5,6] : int list
Why SML see the a and b values as lists, not just simply a and b
Chris already answered this in-depth.
You're passing a as the first argument to helper2, which expects a list as its first argument. And you're passing b as the second argument to helper2, which uses its second argument, b::l2, also a list, as the tail of a list where a is the head. So b must be a list of those lists.
This doesn't make any sense, and is most likely a consequence of confusing syntax: You are passing in what you think of single elements a and b in flatten2, but when you deal with them in helper2 they're now lists where the heads are called a and b. Those are not the same a and b.
How can I revise my code so SML can see a and b as 'a and 'b not lists
You could ditch the helper function to begin with:
fun flatten2 [] = []
| flatten2 ((a,b)::pairs) = a :: b :: flatten2 pairs
The purpose of having a helper function is so that it can accumulate the result during recursion, because this version of flatten2 uses a lot of stack space. It can do this with an extra argument so that flatten2 doesn't need to mention it:
This is the version Chris made.
How to make this code work the way it should be?
You can make this code in a lot of ways. Two ways using explicit recursion were mentioned.
Here are some alternatives using higher-order functions:
(* Equivalent to my first version *)
fun flatten2 pairs =
foldr (fn ((a,b), acc) => a :: b :: acc) [] pairs
(* Equivalent to Chris'es version *)
fun flatten2 pairs =
rev (foldl (fn ((a,b), acc) => b :: a :: acc) [] pairs)
(* Yet another alternative *)
fun concatMap f xs =
List.concat (List.map f xs)
fun flatten2 pairs =
concatMap (fn (a,b) => [a,b]) pairs

Pattern matching on rest of list

I'm trying to pattern match on a list of pairs, where I'm trying to return a list from the list of pair, however I'm having trouble figuring out where to make the recursive call. Without the recursive call I have this:
let countriesInChart (cht: chart) =
match cht with
| [] -> []
| (x,y)::tt -> [x;y]
;;
But naturally this only applies to the first pair in the list and simply returns ["countryA"; "countryB"] without the rest of the list.
With the recursive call this simply only returns an empty list:
let rec countriesInChart (cht: chart) =
match cht with
| [] -> []
| (x,y)::tt -> [x;y]::countriesInChart tt
;;
How would I make the recursive call such that all the pairs in the list would return as a list?
You have this:
[x;y] :: countriesInChart tt
This says to add a new list of two elements onto the front of a list of lists.
I don't think you want a list of lists, you just want a list. So you shouldn't be making a list of two elements.
If x and y are the same type (as I suspect they are), what you probably want is this:
x :: y :: countriesInChart tt
This says to add both x and y individually to the front of the recursively generated list.
You can also write this, which is completely equivalent:
[x; y] # countriesInChart tt
However, this constructs a list of two elements only to throw it away. So it's a tiny bit of extra work for no benefit.

F# return list of list lengths

I am to use combinators and no for/while loops, recursion or defined library functions from F#'s List module, except constructors :: and []
Ideally I want to implement map
I am trying to write a function called llength that returns the list of the lengths of the sublists. For example llength [[1;2;3];[1;2];[1;2;3]] should return [3;2,3]. I also have function length that returns the length of a list.
let Tuple f = fun a b -> f (a, b)
let length l : int =
List.fold (Tuple (fst >> (+) 1)) 0 l
currently have
let llength l : int list =
List.map (length inner list) list
Not sure how I should try accessing my sublists with my restraints and should I use my other method on each sublist? any help is greatly appreciated, thanks!
Since this is homework, I don't want to just give you a fully coded solution, but here are some hints:
First, since fold is allowed you could implement map via fold. The folding function would take the list accumulated "so far" and prepend the next element transformed with mapping function. The result will come out reversed though (fold traverses forward, but you prepend at every step), so perhaps that wouldn't work for you if you're not allowed List.rev.
Second - the most obvious, fundamental way: naked recursion. Here's the way to think about it: (1) when the argument is an empty list, result should be an empty list; (2) when the argument is a non-empty list, the result should be length of the argument's head prepended to the list of lengths of the argument's tail, which can be calculated recursively. Try to write that down in F#, and there will be your solution.
Since you can use some functions that basically have a loop (fold, filter ...), there might be some "cheated & dirty" ways to implement map. For example, via filter:
let mymap f xs =
let mutable result = []
xs
|> List.filter (fun x ->
result <- f x :: result
true)
|> ignore
result |> List.rev
Note that List.rev is required as explained in the other answer.

Index of element in list in Haskell

How can I get the index of the element I am at in haskell when I am using map ?
For example I have this list l = "a+bc?|(de)*fg|h" and I want to know the exact index of the element I am at when I use the map or scanl function.
Amending Nikita Volkov's answer, you can use a function such as:
-- variant of map that passes each element's index as a second argument to f
mapInd :: (a -> Int -> b) -> [a] -> [b]
mapInd f l = zipWith f l [0..]
First of all, if you need an index when processing a list it is a certain sign that you're implementing a suboptimal algorithm, because list is not an index-based structure like array. If you need to deal with indexes you better consider using a vector instead.
Concerning your actual question, you can pair the items of your list with incrementing ints with the following code and then map over the result:
Prelude> zip [0..] "a+bc?|(de)*fg|h" :: [(Int, Char)]
[(0,'a'),(1,'+'),(2,'b'),(3,'c'),(4,'?'),(5,'|'),(6,'('),(7,'d'),(8,'e'),(9,')'),(10,'*'),(11,'f'),(12,'g'),(13,'|'),(14,'h')]

Extracting elements from list in SML

I'm trying to extract the given elements from a list, but I get an Match exception?
The goal is to make my function behave like:
fun extract [#"a",#"b",#"c"] [0,1,0] = [#"a",#"b",#"a"];
And I'm trying to do it like this:
fun extract [] _ = []
| extract xr (y::yr) = List.nth(xr, y) :: extract xr yr;
But as said, I get an
! Uncaught exception:
! Match
Any ideas?
Maybe theres some more List functions I could use for this?
I've head about the curry function, which should make a function into a higher-order function, but I don't really know how that works?
The reason that you get a match error is that there's no case for when the second list is empty, but the first is not (which will always happen unless the first list is empty to begin with because only the second list gets shorter).
Basically you can change the first line to fun extract _ [] = [] and it will work.
And yes, you can also solve this using higher-order function. You can use curry to turn List.nth into a function of type 'a list -> int -> 'a instead of 'a list * int -> 'a. You can then partially apply that function to xr, which turns it into a function of type int -> 'a, which will return the ith list of xr when given a number i. You can then use List.map to apply the function to each number in the list of indices you're given. So the function becomes:
fun extract xr yr = List.map (curry List.nth xr) yr
But what you came up with works fine, so you should just stick with that.