Syntax for list construction / concatenation - list

I've only been at Haskell for two days now, and was wondering what the difference between the two function definitions below are:
Prelude> let swap (x1:x2:xs) = x2:x1:xs
Prelude> swap [1..5]
[2,1,3,4,5]
Prelude> let swap' (x1:x2:xs) = [x2] ++ [x1] ++ xs
Prelude> swap' [1..5]
[2,1,3,4,5]
That is, what makes x2:x1:xs different from [x2] ++ [x1] ++ xs ?
Please and thanks.

The type signatures are a good place to start:
(:) :: a -> [a] -> [a]
(++) :: [a] -> [a] -> [a]
You can find these out with :type (:) and :type (++) in ghci.
As you can see from the type signatures, both are used to produce lists.
The : operator is used to construct lists (and to take them apart again for pattern matching). To make a list [1,2,3] you just build it up with 1 : 2 : 3 : []. The first element of : is the item to add on the front of the list, and the second element is either a list (also built up with : or the empty list signified by []).
The ++ operator is list concatenation. It takes two lists and appends them together. [1,2,3] ++ [4,5,6] is legal, whereas 1 ++ [1,2,3] is not.

This has nothing to do with syntax. (:) and (++) are just different operators. (:) is a constructor who constructs a list from an element and another list. (++) makes a new list that is the concatenation of two lists. Because (++) is not a constructor you can't use it in patterns.
Now we come to Syntax: the notation
[x2]
that you use is a shorthand for
x2:[]
So what you really have done in the second example is:
(x2:[]) ++ (x1:[]) ++ xs
Therefore, when constructing a list, you can't avoid (:), it's ultimatively the only way to do it. Note that you must construct intermediate lists to be able to use (++).

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!

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

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

How to count how many elements are in a list?

I know about the length function, but if I have a list such as [(1,2),(2,3),(3,4)] and try to use length it does not work. I tried to concatenate but that doesn't help. Any idea how?
While the sensible solution to your immediate problem is (2 *) . length, as 9000 pointed out, it is worth dwelling a bit on why length [(1,2),(2,3),(3,4)] doesn't do what you expect. A Haskell list contains an arbitrary number of elements of the same type. A Haskell pair, however, has exactly two elements of possibly different types, which is something quite different and which is not implicitly converted into a list (see this question for further discussion of that point). However, nothing stops us from writing a conversion function ourselves:
pairToList :: (a, a) -> [a]
pairToList (x, y) = [x, y]
Note that the argument of pairToList is of type (a, a); that is, the function only accepts pairs with both elements having the same type.
Given pairToList, we can convert the pairs in your list...
GHCi> map pairToList [(1,2),(2,3),(3,4)]
[[1,2],[2,3],[3,4]]
... and then proceed as you planned originally:
GHCi> (length . concat . map pairToList) [(1,2),(2,3),(3,4)]
6
The concatMap function combines map and concat into a single pass...
GHCi> :t concatMap
concatMap :: Foldable t => (a -> [b]) -> t a -> [b]
... and so your function becomes simply:
GHCi> (length . concatMap pairToList) [(1,2),(2,3),(3,4)]
6
length [(1,2),(2,3),(3,4)] gives you 3 because there are precisely three elements in the list where the elements are tuples, each consisting of two integers. use this function to get all the "elements"
tupleLength :: [(Int, Int)] -> Int
tupleLength = (*2) . length

All combinations of elements of two lists in Haskell

Given two lists, [a, b] and [c, d], I'd like to get the following result:
[(a,c), (a,d), (b,c), (b,d)]
How can I do this in Haskell? Is there a built-in function for this, or should I implement one myself?
[ (x,y) | x<-[a,b], y<-[c,d] ]
This doesn't really require any further explanation, does it?
Applicative style all the way!
λ> :m + Control.Applicative
λ> (,) <$> ['a','b'] <*> ['c','d']
[('a','c'),('a','d'),('b','c'),('b','d')]
(I've eschewed any String syntactic sugar above, in order to stay close to your example.)
For information, (,) is special syntax for a function that takes two arguments and makes a pair out of them:
λ> :t (,)
(,) :: a -> b -> (a, b)
Edit: As noted by leftaroundabout in his comment, you can also use liftA2:
λ> :m + Control.Applicative
λ> let combine = liftA2 (,)
λ> combine "ab" "cd"
[('a','c'),('a','d'),('b','c'),('b','d')]
How can you do this in an imperative pseudocode?
for each element x in [a,b]:
for each element y in [c,d]:
produce (x,y)
In Haskell, this is written as
outerProduct xs ys =
do
x <- xs -- for each x drawn from xs:
y <- ys -- for each y drawn from ys:
return (x,y) -- produce the (x,y) pair
(following comments by leftaroundabout) this is of course extremely close to how liftM2 monadic combinator is defined, so in fact
outerProduct = liftM2 (,)
which is the same as liftA2 (,), and its various re-writes in terms of list comprehensions, concatMap function, >>=, <$> and <*> operators.
Conceptually though this is the stuff of the Applicative – which would be better named as Pairing, – because this pairing up of the elements of two "containers" ⁄ "carriers" ⁄ whatever is exactly what Applicative Functor is about. It just so happens that Haskell's do notation works for monads, and not (yet) for applicatives.
In some sense compile-time nested loops are Applicative ⁄ Pairing functors; Monads add the ability to create nested loops on the fly, depending on the values produced by an "outer" enumeration.
The most inuitive would be using list comprehension, other aproaches include using applicative functors:
(,) <$> [1,2,3] <*> [4,5,6]
So what does this do?
Remember that (,) :: a -> b -> (a, b) Takes two arguments and returns a tuple.
<$> is acutally fmap, (<$>) :: Functor f => (a -> b) -> f a -> f b
It takes a function and lift it. In this case it takes (,) and lift it to work on list. So let x = (,) <$> [1,2] would generate x :: [b -> (Integer, b)] which is the the list of functions that takes b and returns tuple with one fixed argument (Integer,b). Finally we apply it using <*> to generate all the combinations.
use List Comprehension:
s = [a,b]
s' = [c,d]
all_combinations = [(x,y) | x <- s, y <- s']