Apppend a list in a list of list - Haskell - list

I'm trying to do a function in haskell. The purpose of the function is to add a list to an existing list of list.
[Int] -> [[Int]] -> [[Int]]
I wish it would work like :
[1] -> [[2],[3]] -> [[2],[3],[1]]
I would like to know how I can proceed to do that. There is an existing included function to do that?

You can wrap the element [1] in a singleton list, and then append the two lists with (++) :: [a] -> [a] -> [a]. So you can implement such function with:
addlast :: a -> [a] -> [a]
addlast x ys = ys ++ [x]
The (++) function however will usually take linear time in the number of elements of the left operand (so ys), which makes it computationally expensive. Therefore it is usually better if order does not matter to prepend to a list.
In the extra package [Hackage], you can make use of snoc :: [a] -> a -> [a]. In that case, this is thus a "flipped" version of snoc:
import Data.List.Extra(snoc)
addlast :: a -> [a] -> [a]
addlast = flip snoc

Related

Concatenation in Haskell and confusion with AList ([a] -> [a])

I have a project where we are improving the speed of concatenating a list in Haskell.
I'm new to Haskell and confused about AList ([a] -> [a]) Specifically how to convert my AppendedList to a regular List. Any help would be appreciated.
newtype AppendedList a = AList ([a] -> [a])
-- List[5] is represented as AList (\x -> 5:x)
-- This function takes an argument and returns the AppendedList for that
single :: a -> AppendedList a
single m = AList (\x -> m : x)
-- converts AppendedList to regular List
toList :: AppendedList a -> [a]
toList = ???
The toughest part is to not give you the answer directly :)
If you remember how lists are constructed in Haskell: [1, 2, 3] = 1 : 2 : 3 : [], with [] being the empty list.
Now let's "follow the types" (we also call this thought process TDD for Type Driven Development) and see what you have at hand:
toList :: AppendedList a -> [a]
toList (AList listFunction) = ???
and listFunction has the type [a] -> [a]. So you need to provide it a polymorphic list (i.e. a list of any type) so that it gives you back a list.
What is the only list of any type you know of? Pass this list to listFunction and everything will compile, which is a good indicator that it's probably right :D
I hope that helps without providing the plain answer (the goal is for you to learn!).
AppendedList a is a type.
AList f is a datum of that type, with some function f :: [a] -> [a] "inside it".
f is a function from lists to lists with the same type of elements.
We can call it with some_list :: [a] to get resulting_list :: [a]:
f :: [a] -> [a]
some_list :: [a]
-------------------------
f some_list :: [a]
resulting_list :: [a]
resulting_list = f some_list
We can use resulting_list as some_list, too, i.e..
resulting_list = f resulting_list
because it has the same type, that fits f's expectations (and because of Haskell's laziness). Thus
toList (...) = let { ... = ... }
in ...
is one possible definition. With it,
take 2 (toList (single 5))
would return [5,5].
edit: Certainly [5,5] is not the list containing a single 5. Moreover, take 4 ... would return [5,5,5,5], so our representation contains any amount of fives, not just one of them. But, it contains only one distinct number, 5.
This is reminiscent of two Applicative Functor instances for lists, the [] and the ZipList. pure 5 :: [] Int indeed contains just one five, but pure 5 :: ZipList Int contains any amount of fives, but only fives. Of course it's hard to append infinite lists, so it's mainly just a curiosity here. A food for thought.
In any case it shows that there's more than just one way to write a code that typechecks here. There's more than just one list at our disposal here. The simplest one is indeed [], but the other one is .... our list itself!

Unpair list of tuples

I have this excercise in Haskell where we have a list of tuples and we need to unpair them and put them into different lists.
Desired outcome:
Main> unpair [(1,2),(3,4),(5,6)]
([1,3,5],[2,4,6])
My code, but I get some errors:
unpair :: [(a,b)] -> ([a],[b])
unpair list = ([a|a<-list.fst], [b|b<-list.snd])
errors:
Template.hs:8:22:
Couldn't match expected type `b0 -> c0' with actual type `[(a, b)]'
Relevant bindings include
list :: [(a, b)] (bound at Template.hs:8:8)
unpair :: [(a, b)] -> ([a], [b]) (bound at Template.hs:8:1)
In the first argument of `(.)', namely `list'
In the expression: list . fst
Template.hs:8:22:
Couldn't match expected type `[a]'
with actual type `(b0, b1) -> c0'
Relevant bindings include
list :: [(a, b)] (bound at Template.hs:8:8)
unpair :: [(a, b)] -> ([a], [b]) (bound at Template.hs:8:1)
In the expression: list . fst
In a stmt of a list comprehension: a <- list . fst
In the expression: [a | a <- list . fst]
Template.hs:8:39:
Couldn't match expected type `b2 -> c1' with actual type `[(a, b)]'
Relevant bindings include
list :: [(a, b)] (bound at Template.hs:8:8)
unpair :: [(a, b)] -> ([a], [b]) (bound at Template.hs:8:1)
In the first argument of `(.)', namely `list'
In the expression: list . snd
Template.hs:8:39:
Couldn't match expected type `[b]'
with actual type `(a0, b2) -> c1'
Relevant bindings include
list :: [(a, b)] (bound at Template.hs:8:8)
unpair :: [(a, b)] -> ([a], [b]) (bound at Template.hs:8:1)
In the expression: list . snd
In a stmt of a list comprehension: b <- list . snd
In the expression: [b | b <- list . snd]
The question also states to try to do it with list comprehensions.
Thanks
This is only slightly hinted to by your error message. The problem you have is that you are mis-using the . operator. You might have programmed in an object-oriented language before where list.fst calls a function fst on the list object. This is not the case in Haskell where . is an infix function used to compose two functions.
What you really want to do is to pick tuples from your list, and then apply fst/snd on those tuples one at a time. For example:
[fst a | a <- list]
You can also use pattern matching and skip fst/snd altogheter, but it is a matter of opinion if this is better or worse:
[a | (a, _) <- list]
You're almost right! You've just got some minor errors:
In Haskell, you can't do list.fst - that is syntactically valid, but the . operator doesn't do the same thing in Haskell as it does in other languages. fst is a function and should be used as such - try applying it to a value e.g. fst list.
More significantly, you can't apply fst or snd to a list like list; as Haskell is a strongly typed language, these functions must be applied to a single value, not a list. Try moving these functions to the left of the bar e.g. to get all the fst values in a list, use [fst a | a <- list], meaning 'for each value a in list, apply fst to a'.

Haskell Lists in List

I'm very new on Haskell, and I'm trying the following:
To obtain [1,2,3] from [[1,2,3],[4,5,6]]?
example :: [[a]] -> [a]
example [] = []
example [x:xs] = [x]
This example is returning [1] when input is [[1,2,3]] and if I add an other element in the main List, like [[1,2,3],[3,4,5]] then I have a Non-exhaustive pattern function.
You are quite close. In fact what you here want is some sort of "safe" head.
A list [a] has two constructors:
the empty list [], you cover this in the first case; and
the "cons" (x:xs).
It looks like you cover that in the second case, but in fact you do not: you put the pattern within square brackets. As a result, Haskell interprets your pattern as [(x:xs)]. So it thinks you match a singleton list (a list with one element), and that x is the head of the sublist, and xs the tail of the sublist.
In fact you want to cover (x:xs). If we use this pattern, there is another problem: x is the head of the list, so it has type [a]. Therefore we should return x, not [x], since in the latter case, we would wrap the sublist back in a list.
So a correct function is:
example :: [[a]] -> [a]
example [] = []
example (x:_) = x -- round brackets, x instead of [x]
Note that since we are not interested in the tail here, we use an underscore _. If you compile with all warnings (-Wall, or more specific -Wunused-matches) Haskell will otherwise complain about the fact that you declare a variable that you do not use.
Generalizing to a safeHead function
We can generalize this to some sort of generic safeHead :: b -> (a -> b) -> [a] -> b function:
safeHead :: b -> (a -> b) -> [a] -> b
safeHead d _ [] = d
safeHead _ f (x:_) = f x
Here we thus pass three arguments to safeHead: a value (of type b) we should return in case the list is empty; a function to post-process the head (type a -> b), and the list to process. In that case the example is equivalent to:
example :: [[a]] -> [a]
example = safeHead [] id
But we can also return a Maybe [a] here:
example2 :: [a] -> Maybe a
example2 = safeHead Nothing Just

Haskell swap nested list

I have this function:
swap [] = []
swap [a] = [a]
swap a = last a : (init . tail $ a) ++ [head a]
If I use this on a list with lists, it just turns each list around, and not the elements in each list. What am I missing here?
swap takes a list of things, and exchanges its first element for its last. Since there is nothing in there about looking inside of those elements at all, it definitely will not modify any of the elements inside of a list.
But if you have a list of things, and you want to perform some modification of each item in the list, there is a function for that already: map. And the modification you want to perform is swap, so let's see how the types line up.
map :: ( a -> b) -> [a] -> [b]
swap :: [a] -> [a]
map swap :: [[a]] -> [[a]]
So map swap takes a list of lists, and swaps each of those sublists, without changing the order of the "larger" list at all.

How can say that a function input should be a list?

I need to prototype a function, saying toList, which takes a list as its only argument, and returns a list of lists (whose type is the same that the original list).
For example [Char] will give us a [[Char]].
I've tried :
(List a) => a -> [a]
which can't work as the Class List does not exist.
How should I do then ?
Thanks in advance
Try this:
f :: [a] -> [[a]]
Tails is a good example of this:
tails :: [a] -> [[a]]
Usage:
tails [1,2,3] == [[1,2,3], [2,3], [3],[]]