[[Int]] -> [Int] with multiply - haskell

I try to learn Haskell and I don't know how to create a function which takes a list of lists and multiplies each element in this list e.g.
[[2,3], [8,3,2], [2,10,1], [2,2,2,2]] -> [6,48,20,16]
I try something like this but it doesn't work. If anyone knows how to do this will be really helpfully for me:
listOfProductInt :: [[Int]] -> [Int]
listOfProductInt [] = []
listOfProductInt lists = foldl (\y x-> multipleInts x concat) [] lists
multipleInts :: (Num a) => [a] -> a
multipleInts list1 = foldl (\y x -> y * x) 1 list1

Very simple really, you need map:
map product [[2,3],[8,3,2],[2,10,1],[2,2,2,2]]
The product function multiplies all elements in a list. It is included in the Prelude, which is imported by default. In other words, it is normally available.
The map function applies that function to each element in the list.

If you prefer a solution with folds only, first a couple of rules of thumb:
Never use foldl (“lazy† left fold”), except in very specific circumstances (which you won't encounter until you've long learned the subtleties).
Use foldr (lazy right fold) for deconstructing lists, if the result is lazy. In particular, this is usually the right choice if your fold produces a list again: foldr will only consume the list by demand, and it doesn't keep a reference to the original head, hence it works smoothly even on infinite lists and avoids memory blowup (in fact, the garbage collector can reclaim parts of the list that are already processed, before the processing is finished!)
Use foldl' (strict left fold) for “atomic” operations like computing the sum of all values in a list.
So let's start with
listOfProductInt :: [[Int]] -> [Int]
-- listOfProductInt [] = [] -- no need for that, folds already handle the empty case.
listOfProductInt lists = foldr _ [] lists
multipleInts :: (Num a) => [a] -> a
multipleInts list1 = foldl' _ 1 list1
GHC will inform you
/tmp/wtmpf-file9164.hs:4:32:
Found hole ‘_’ with type: [Int] -> [Int] -> [Int]
Relevant bindings include
lists :: [[Int]] (bound at /tmp/wtmpf-file9164.hs:4:18)
listOfProductInt :: [[Int]] -> [Int]
(bound at /tmp/wtmpf-file9164.hs:4:1)
In the first argument of ‘foldr’, namely ‘_’
Unfortunately this is not as informtive as usually because both the result and the individual sub-lists have type [Int]. I'll annotate the type:
[Int] -- the sublist we're focusing on
-> [Int] -- the result of the future product-computations yet to be done
-> [Int] -- the result at this point of the computation
Now, for handling the sublist that's on the agenda first, we have multipleInts. So, it should look something like
listOfProductInt lists = foldr (\l -> _ (multipleInts l)) [] lists
to which GHC replies
/tmp/wtmpf-file9164.hs:4:39:
Found hole ‘_’ with type: Int -> [Int] -> [Int]
Relevant bindings include
l :: [Int] (bound at /tmp/wtmpf-file9164.hs:4:34)
lists :: [[Int]] (bound at /tmp/wtmpf-file9164.hs:4:18)
listOfProductInt :: [[Int]] -> [Int]
(bound at /tmp/wtmpf-file9164.hs:4:1)
In the expression: _
In the expression: _ (multipleInts l)
In the first argument of ‘foldr’, namely
‘(\ l -> _ (multipleInts l))’
You may recognise Int -> [Int] -> [Int], or generally a -> [a] -> [a], as the signature of the cons-operator (:), and that's what's needed here:
listOfProductInt lists = foldr (\l -> (:) (multipleInts l)) [] lists
or, using point-free composition,
listOfProductInt = foldr ((:) . multipleInts) []
Proceed with the implementation of multipleInts:
/tmp/wtmpf-file9164.hs:7:29:
Found hole ‘_’ with type: a -> a -> a
Where: ‘a’ is a rigid type variable bound by
the type signature for multipleInts :: Num a => [a] -> a
at /tmp/wtmpf-file9164.hs:6:17
Relevant bindings include
list1 :: [a] (bound at /tmp/wtmpf-file9164.hs:7:14)
Well, a -> a -> a where a fulfills a Num constraint? That's just the simple product operation!
multipleInts list1 = foldl' (*) 1 list1
†foldl is only lazy in the values, but not in the spine. In practice, this tends to give you the worst of both worlds: the processor is immediately clogged with having to handle the whole list, but instead of actually doing useful computations, it merely builds up stacks of memory-hogging laziness-thunks.

Related

Length with foldl and foldr

I have two functions computing the length of a list of integers
lengthFoldl :: [Int] -> Int
lengthFoldl xs = (foldl (\_ y -> y+1) 0 xs)
and
lengthFold :: [a] -> Int
lengthFold xs = foldr (\_ y -> y+1) 0 xs
they are the same except one uses foldr and one foldl.
But when trying to compute the length of any list [1 .. n] I get a wrong result (one too big) from lengthFoldl.
To complement joelfischerr's answer, I'd like to point out that a hint is given by the types of your functions.
lengthFoldl :: [Int] -> Int
lengthFold :: [a] -> Int
Why are they different? I guess you might had to change the first one to take an [Int] since with [a] it did not compile. This is however a big warning sign!
If it is indeed computing the length, why should lengthFoldl care about what is the type of the list elements? Why do we need the elements to be Ints? There is only one possible explanation for Int being needed: looking at the code
lengthFoldl xs = foldl (\_ y -> y+1) 0 xs
we can see that the only numeric variable here is y. If y is forced to be a number, and list elements are also forced to be numbers, it seems as if y is taken to be a list element!
And indeed that is the case: foldl passes to the function the accumulator first, the list element second, unlike foldr.
The general thumb rule is: when type and code do not agree, one should think carefully about which one is right. I'd say that most Haskellers would think that, in most cases, it is easier to get the type right than the code right. So, one should not just adapt the type to the code to force it to compile: a type error can instead witness a bug in the code.
Looking at the type definitions of foldl and foldr it becomes clear what the issue is.
:t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
and
:t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
One can see that the foldr takes the item of the list and the second argument into the function and foldl takes the second argument and the item of the list into the function.
Changing lengthFoldl to this solves the problem
lengthFoldl :: [Int] -> Int
lengthFoldl xs = foldl (\y _ -> y+1) 0 xs
Edit: Using foldl instead of foldl' is a bad idea: https://wiki.haskell.org/Foldr_Foldl_Foldl'

Why doesn't this function work if I use "[xs]" instead of "xs"?

split :: [a] -> Int -> ([a], [a])
split [xs] n =
(take n [xs], drop n [xs])
The same code works if I give the variable as xs instead of [xs], signatures are same in both cases. Using [xs] gives the error that pattern is non-exhaustive. I understand it's telling that the input I gave is not covered by my code, but not clear what is happening under the hood.
Test input: [1,2,3] 2.
Somehow a lot of people think that [xs] as pattern means that you unify a list with xs. But this is incorrect, since the function signature (either derived implicitly, or stated explicitly) already will prevent you to write code where you call the function with a non-list item.
A list has two constructors:
the empty list []; and
the "cons" (h : t) with h the head (first element), and t the tail (a list with the remaining elements).
Haskell however introduces some syntactical sugar as well. For example [1] is short for (1:[]), and [1, 4, 2] for (1:(4:(2:[]))).
So that means that if you write [xs], behind the curtains you defined a pattern (xs: []) which thus means you match all lists with exactly one element, and that single element (not the entire list) is then xs.
Anyway, the solution is to use:
split xs n = (take n xs, drop n xs)
Since both take :: Int -> [a] -> [a] and drop :: Int -> [a] -> [a] have in the signature that xs is supposed to be a list, Haskell will derive automatically that n is supposed to be an Int, and xs an [a].
Note that you can use splitAt :: Int -> [a] -> ([a], [a]) as well. We can make the signature equivalent to the one you target with:
split = flip splitAt

How can I use generic type annotations to describe a recursive data type?

Here's the function:
comboGraph :: [a] -> Int -> [b]
comboGraph _ 0 = []
comboGraph [] _ = []
comboGraph (x:xs) n =
(buildEdges x xs) : comboGraph xs n
where buildEdges h t = (h, comboGraph t (n-1))
Ths function takes in a list of type a, a number, and returns a list of type b. As you can see, though, type b is actually a recursive type -- it will be something along the lines of [(a, [(a, b1)])]. When I try to compile, I get this error:
• Couldn't match type ‘b’ with ‘(a, [b0])’
‘b’ is a rigid type variable bound by
the type signature for:
comboGraph :: forall a b. [a] -> Int -> [(a, [b])]
at xxx.hs:15:15
Expected type: [(a, [b])]
Actual type: [(a, [(a, [b0])])]
• In the expression: (buildEdges x xs) : comboGraph xs n
In an equation for ‘comboGraph’:
comboGraph (x : xs) n
= (buildEdges x xs) : comboGraph xs n
where
buildEdges h t = (h, comboGraph t (n - 1))
How do I properly annotate this function?
To make the issue a bit more evident, let's substitute the definition of buildEdges in the final case of your definition:
comboGraph (x:xs) n =
(x, comboGraph xs (n-1)) : comboGraph xs n
The result of comboGraph is supposed to be a list, but one whose elements are pairs that also have a comboGraph result (i.e. a list of the same type) within. As the type error you got says, that doesn't work -- it's as if you wanted a list with two tails. The fix is switching to a different data structure that reflects what you are trying to do:
-- Feel free to substitute better names.
data Combo a = Empty | Node a (Combo a) (Combo a)
deriving (Eq, Ord, Show)
Empty covers the base cases which used to result in an empty list, while Node has one appropriately-typed field for each of the things you want to combine in the recursive case. comboGraph then becomes:
comboGraph :: [a] -> Int -> Combo a
comboGraph _ 0 = Empty
comboGraph [] _ = Empty
comboGraph (x:xs) n = Node x (comboGraph xs (n-1)) (comboGraph xs n)
(Note that Combo is actually a binary tree with values on the nodes.)
I like the other answer, and I think you should use it. But it makes some reasoning leaps that require some intuition, and it can be hard to get this intuition without doing things the mechanical way a few times. So in this answer, I will show how to start with a failing definition like the one you have, "turn a crank", and mechanically get a solution that does work. The technique below can be applied to any infinite type error.
You have the following clause (paraphrased slightly):
comboGraph (x:xs) n =
(x, comboGraph xs (n-1)) : {- ... -}
Just doing some straightforward type inference reasoning, we can see that comboGraph takes a list of some type (from the fact that it pattern matches on x:xs) and a number (from the fact that it subtracts one). Let's pick a concrete (monomorphic! but not yet known) type a for the list elements and see what we can infer about what it returns.
Well, it clearly returns a list with tuples inside. And the first part of the tuple is just an a. What about the second part? The second part of the tuple is... whatever type comboGraph returns. So comboGraph returns a type t satisfying the equation:
t = [(a, t)]
The only solution to this equation is [(a, [(a, [(a, [(a, ...)])])])]. Such infinite types don't exist raw in Haskell. But there is a standard trick to get quite close: use (type-level) recursion by introducing a newtype. We're solving for t, but Haskell types have to start with an upper-case letter, so we'll name our solution to this equation T.
newtype T a = T [(a, T a)] deriving Show
Now we don't quite have T a ~ [(a, T a)], but we do have an isomorphism: namely, \(T xs) -> xs :: T a -> [(a, T a)] and T :: [(a, T a)] -> T a are inverses. So now we can write your comboGraph definition by exploiting this isomorphism. Let's name the other half of the isomorphism:
unT :: T a -> [(a, T a)]
unT (T xs) = xs
So:
comboGraph (x:xs) n =
T ((x, comboGraph xs (n-1)) : unT (comboGraph xs n))
The base cases have to get wrapped in T, as well, of course:
comboGraph _ 0 = T []
comboGraph [] _ = T []
Try it in ghci:
> comboGraph "abc" 3
T [('a',T [('b',T [('c',T [])]),('c',T [])]),('b',T [('c',T [])]),('c',T [])]

Haskell:Non-exhaustive patterns in function bean [duplicate]

split :: [a] -> Int -> ([a], [a])
split [xs] n =
(take n [xs], drop n [xs])
The same code works if I give the variable as xs instead of [xs], signatures are same in both cases. Using [xs] gives the error that pattern is non-exhaustive. I understand it's telling that the input I gave is not covered by my code, but not clear what is happening under the hood.
Test input: [1,2,3] 2.
Somehow a lot of people think that [xs] as pattern means that you unify a list with xs. But this is incorrect, since the function signature (either derived implicitly, or stated explicitly) already will prevent you to write code where you call the function with a non-list item.
A list has two constructors:
the empty list []; and
the "cons" (h : t) with h the head (first element), and t the tail (a list with the remaining elements).
Haskell however introduces some syntactical sugar as well. For example [1] is short for (1:[]), and [1, 4, 2] for (1:(4:(2:[]))).
So that means that if you write [xs], behind the curtains you defined a pattern (xs: []) which thus means you match all lists with exactly one element, and that single element (not the entire list) is then xs.
Anyway, the solution is to use:
split xs n = (take n xs, drop n xs)
Since both take :: Int -> [a] -> [a] and drop :: Int -> [a] -> [a] have in the signature that xs is supposed to be a list, Haskell will derive automatically that n is supposed to be an Int, and xs an [a].
Note that you can use splitAt :: Int -> [a] -> ([a], [a]) as well. We can make the signature equivalent to the one you target with:
split = flip splitAt

type error when compiling

I don't understand why the following code won't compile:
append :: [a] -> [a] -> [a]
append xs ys = foldr (:) ys xs
traverse :: a -> [a] -> [[a]]
traverse x [] = [[x]]
traverse x (y:ys) = append [(x:y:ys)] (map (y:) (traverse x ys))
comb :: [a] -> [[a]]
comb [] = [[]]
comb (x:[]) = [[x]]
comb (x:y:[]) = [[x,y],[y,x]]
comb (x:xs) = map (traverse x) (comb xs)
It produces the following error:
pr27.hs:13:20:
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for comb :: [a] -> [[a]] at pr27.hs:10:1
Expected type: [a] -> [a]
Actual type: [a] -> [[a]]
In the return type of a call of `traverse'
In the first argument of `map', namely `(traverse x)'
Failed, modules loaded: none
But when I load just traverse and use it in an expression similar to the above, I get the desired result. What's going on?
Main> map (traverse 3) [[1,2],[2,1]]
[[[3,1,2],[1,3,2],[1,2,3]],[[3,2,1],[2,3,1],[2,1,3]]]
The problem is that comb has to return a value of type [[a]]. traverse returns a value of type [[a]], so mapping it over another list produces [[[a]]], which has too many levels of nesting.
Let's look at map. It has a type map :: (x -> y) -> [x] -> [y]. traverse x has a type [a] -> [[a]]. Now we need to combine the two. To do this, we replace x with [a] and y with [[a]], getting ([a] -> [[a]]) -> [[a]] -> [[[a]]]. This clearly shows the result of mapping traverse has to have at least three levels of nesting.
If you look at your example, this is what you actually get. For comb, you only want one two levels deep.
The reason your example worked in GHCi is because an expression there can have any type. Your map (traverse 3) [[1,2], [2,1]] expression is perfectly legal; however, it has the type Num a => [[[a]]], which is a list of lists of lists of numbers. (Try it: :t map (traverse 3) [[1,2], [2,3]].) However, the type of comb is [a] -> [[a]]. This means the result has to be a list of lists, not a list of lists of lists. So the issue is that map (traverse 3) is incompatible with comb, not that it is illegal by itself.

Resources