Haskell component-by-component addition - haskell

I am trying do to the component-by-component addition of a list of tuples with the use of higher functions. The result should be the (sum of the first component, sum on the second component).
sumPointwise :: Num a => [(a,a)] -> (a,a)
sumPointwise tl = (sumPw1, sumPw2) -- 42:1
where sumPw1 = foldr (\ x y -> (fst x) + (fst y)) 0 tl
sumPw2 = foldr (\ x y -> (snd x) + (snd y)) 0 tl
But I'm getting the following error:
Couldn't match type `a' with `(a, b0)'
`a' is a rigid type variable bound by
the type signature for sumPointwise :: Num a => [(a, a)] -> (a, a)
at .hs:42:1
In the first argument of `fst', namely `y'
In the second argument of `(+)', namely `(fst y)'
In the expression: (fst x) + (fst y)
It seems like the lambda function is wrong. But I don't get it.
Thanks for your help!

The second argument of foldr is aggregate value: foldr :: (a -> b -> b) -> b -> [a] -> b. So, your expressions should look like
sumPw1 = foldr (\ x s -> (fst x) + s) 0 tl
More succinct way of solving your task is
sumPointwise tl = let (xs, ys) = unzip tl in (sum xs, sum ys)

Related

Why foldr (\ x xs -> x : x : xs) [] wont work?

I'm trying to see the difference in these 2 functions:
dupli = foldl (\acc x -> acc ++ [x,x]) []
dupli = foldr (\ x xs -> x : x : xs) []
I know the difference between foldl and foldr but for the examples I've seen on how it works, using (+), it looks the same except for the method of summing.
Why
dupli = foldr (\acc x -> acc ++ [x,x]) []
gives
/workspaces/hask_exercises/exercises/src/Lib.hs:142:27: error:
* Occurs check: cannot construct the infinite type: a ~ [a]
Expected type: [a]
Actual type: [[a]]
* In the expression: acc ++ [x, x]
In the first argument of `foldr', namely
`(\ acc x -> acc ++ [x, x])'
In the expression: foldr (\ acc x -> acc ++ [x, x]) []
* Relevant bindings include
x :: [a] (bound at src/Lib.hs:142:22)
acc :: [[a]] (bound at src/Lib.hs:142:18)
dupli' :: t [[a]] -> [a] (bound at src/Lib.hs:142:1)
|
142 | dupli' = foldr (\acc x -> acc ++ [x,x]) []
| ^^^^^^^^^^^^
exactly?
Look at the type signatures. (Note: I'm specializing both of these to [] rather than a general Foldable for simplicity here)
foldl :: (b -> a -> b) -> b -> [a] -> b
foldr :: (a -> b -> b) -> b -> [a] -> b
So in foldl, the "accumulator argument" is the first argument to the folding function, whereas in foldr, it's the second.
You mention (+). (+) is a function where the left-hand and right-hand arguments have the same type, so you wouldn't notice the difference. Specifically,
(+) :: Num a => a -> a -> a
But (:) is different.
(:) :: a -> [a] -> [a]
Since your initial accumulator is, in both cases, [], you can use (:) in the foldr case since the accumulator type [a] is the second argument, but in the foldl case we're required to do some tricks with ++.

Couldn't match expected type [Int] Haskell

I am new to Haskell so I don't quite understand most of its errors. I have encountered an error trying to make a higher order function that uses foldl() to read a list and then multiply it by 2 (it automatically reverses it) and I use another another foldl() just to read it, in so reversing it to its original order.
I would be thankful for any help I receive.
here's the error
• Couldn't match expected type ‘[Int]’
with actual type ‘t0 Integer -> [Integer]’
• Probable cause: ‘foldl’ is applied to too few arguments
In the first argument of ‘reverses’, namely
‘(foldl (\ acc x -> (2 * x) : acc) [])’
In the expression: reverses (foldl (\ acc x -> (2 * x) : acc) [])
In an equation for ‘multthr’:
multthr = reverses (foldl (\ acc x -> (2 * x) : acc) [])
|
16 | multthr = reverses(foldl(\acc x-> (2*x):acc)[])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
here's the source code
reverses::[Int] ->[Int]
reverses = foldl(\acc x-> x:acc)[]
multthr::[Int]->([Int]->[Int])
multthr = reverses(foldl(\acc x-> (2*x):acc)[])
You need to compose your two foldl's with (.), instead of applying one to the other:
reverses :: [a] -> [a]
reverses = foldl (\acc x-> x:acc) []
---- multthr :: [Int] -> ([Int] -> [Int]) -- why??
multthr :: [Int] -> [Int]
---- multthr = reverses (foldl(\acc x-> (2*x):acc)[]) -- causes error
multthr = reverses . foldl (\acc x-> (2*x):acc) []
so that we have
> multthr [1..5]
[2,4,6,8,10]
it :: [Int]
(.) is the functional composition, defined as (f . g) x = f (g x).
Instead of doing the two foldl's you can do one foldr,
mult2 = foldr (\x r -> (2*x) : r) []
but then this is nothing else but, simply, map (2*).

Type errors using filter and lambda?

I've just started learning Haskell about a week ago, and am still struggling a lot with type matching with my functions. I am trying to write a function that takes a list and integer n, and removes every nth index from that list. It's problem 16 in H99: 99 Haskell Problems. Anyways here is the code:
dropN :: (Ord a) => [a] -> Int -> [a]
dropN lst n = filter (\x -> ((elemIndex x lst) + 1) `mod` n /= 0, lst)
And here are the errors I am receiving:
Prelude> :l P10
[1 of 1] Compiling Main ( P10.hs, interpreted )
P10.hs:34:15:
Couldn't match expected type `[a]' with actual type `[a0] -> [a0]'
Relevant bindings include
lst :: [a] (bound at P10.hs:34:7)
dropN :: [a] -> Int -> [a] (bound at P10.hs:34:1)
Probable cause: `filter' is applied to too few arguments
In the expression:
filter (\ x -> (elemIndex x lst) `mod` n /= 0, lst)
In an equation for `dropN':
dropN lst n = filter (\ x -> (elemIndex x lst) `mod` n /= 0, lst)
P10.hs:34:22:
Couldn't match expected type `a0 -> Bool'
with actual type `(a -> Bool, [a])'
Relevant bindings include
lst :: [a] (bound at P10.hs:34:7)
dropN :: [a] -> Int -> [a] (bound at P10.hs:34:1)
In the first argument of `filter', namely
`(\ x -> (elemIndex x lst) `mod` n /= 0, lst)'
In the expression:
filter (\ x -> (elemIndex x lst) `mod` n /= 0, lst)
In an equation for `dropN':
dropN lst n = filter (\ x -> (elemIndex x lst) `mod` n /= 0, lst)
P10.hs:34:53:
Couldn't match expected type `Maybe Int' with actual type `Int'
In the second argument of `mod', namely `n'
In the first argument of `(/=)', namely `(elemIndex x lst) `mod` n'
Failed, modules loaded: none.
What you are passing to filter is a tuple (pair) consisting of the filtering function and the list. The type of filter is
filter :: (a -> Bool) -> [a] -> [a]
Therefore you should pass two arguments to filter:
dropN lst n = filter (\x -> ((elemIndex x lst) + 1) `mod` n /= 0) lst
In Haskell, you pass arguments to a function by seperating them with spaces. For example,
f a b
means "Invoke f with the first argument equal to a and the second argument equal to b".

Haskell: List Comprehensions and higher-order functions

I've tried to transform the following list comprehension:
f xs = [ x+8 | (x,_) <- xs ]
using higher-order functions.
My first solution was:
f' xs = map (\(x,_) -> x+8) xs
After I tried various other approaches, I found out that the following also works:
f' xs = map((+8).fst) xs
Both versions of f' give the same (correct) output, but I don't understand why (+8).fst is equal to \(x,_) -> x+8 when using map on a list of tuples.
The definition of fst is
fst :: (a, b) -> a
fst (a, _) = a
and the definition of (.) is
(.) :: (b -> c) -> (a -> b) -> a -> c
(f . g) = \x -> f (g x)
If we use these definitions to expand your function, we get
f' xs = map ((+8) . fst) xs
f' xs = map (\x -> (+8) (fst x)) xs -- definition of (.)
f' xs = map (\x -> (+8) ((\(a, _) -> a) x)) -- definition of fst
f' xs = map (\(a, _) -> (+8) a) -- we can move the pattern matching
f' xs = map (\(a, _) -> a + 8) -- expand section
Both versions of f' give the same (correct) output, but I don't understand why (+8).fst is equal to (x,_) -> x+8 when using map on a list of tuples.
The type of fst is:
fst :: (a, b) -> a
and what it does is it takes the first element of a pair (a tuple of two elements).
The type of (+8) is:
(+8) :: Num a => a -> a
and what it does is it takes as input a Num, applies + 8 to it and returns the result.
Now, the type of (+8) . fst is:
((+8).fst) :: Num c => (c, b) -> c
which is the composition of fst and (+8). Specifically it's the function that takes as input a pair, extracts the first element and adds 8 to it.
This can be easily seen by seen an example:
((+8).fst) (3, 'a')
-- 11
The same thing happens with \ (x, _) -> x + 8. You take a pair as input (in the lambda), pattern match the first argument to x, increment it by 8 and return it:
(\ (x, _) -> x + 8) (3, 'a')
-- 11

Y combinator, Infinite types and Anonymous recursion in Haskell

I was trying to solve the maximal subsequence sum problem and came up with a neato solution
msss :: (Ord a, Num a) => [a] -> a
msss = f 0 0
f gmax _ [] = gmax
f gmax lmax (x:xs) =
let g = max (lmax + x)
in f (g gmax) (g 0) xs
You call the wrapper function msss, which then calls f, which in turn actually does the work.
The solution is good and afaik working correctly. If for some reason I had to solve the maximal subsequence sum problem in production code, that is how I would do it.
However that wrapper function really bugs me. I love it how in haskell, if you are persistent enough you can write your entire program on a single line, to truly drive home the point that a program is pretty much just one big expression. So I figured I'd try and eliminate the wrapper function for the extra challenge.
It's now I run into the classic problem: How to do anonymous recursion? How do you do recursion when you can't give names to functions? Thankfully the fathers of computing solved this problem ages ago by discovering Fixed-Point Combinators, with the most popular being the Y Combinator.
I've made various attempts to get a Y combinator set up, but they can't get past the compiler.
msss' :: [Int] -> Int
msss' = (\y f x -> f (y y f) x)
(\y f x -> f (y y f) x)
(\g' gmax lmax list -> if list == []
then gmax
else g' (max gmax lmax + head list)
(max 0 lmax + head list)
tail list)
just gives
Prelude> :l C:\maxsubseq.hs
[1 of 1] Compiling Main ( C:\maxsubseq.hs, interpreted )
C:\maxsubseq.hs:10:29:
Occurs check: cannot construct the infinite type:
t0 = t0 -> (([Int] -> Int) -> [Int] -> Int) -> [Int] -> Int
In the first argument of `y', namely `y'
In the first argument of `f', namely `(y y f)'
In the expression: f (y y f) x
C:\maxsubseq.hs:11:29:
Occurs check: cannot construct the infinite type:
t0 = t0 -> (([Int] -> Int) -> [Int] -> Int) -> [Int] -> Int
In the first argument of `y', namely `y'
In the first argument of `f', namely `(y y f)'
In the expression: f (y y f) x
C:\maxsubseq.hs:12:14:
The lambda expression `\ g' gmax lmax list -> ...'
has four arguments,
but its type `([Int] -> Int) -> [Int] -> Int' has only two
In the second argument of `\ y f x -> f (y y f) x', namely
`(\ g' gmax lmax list
-> if list == [] then
gmax
else
g' (max gmax lmax + head list) (max 0 lmax + head list) tail list)'
In the expression:
(\ y f x -> f (y y f) x)
(\ y f x -> f (y y f) x)
(\ g' gmax lmax list
-> if list == [] then
gmax
else
g' (max gmax lmax + head list) (max 0 lmax + head list) tail list)
In an equation for `msss'':
msss'
= (\ y f x -> f (y y f) x)
(\ y f x -> f (y y f) x)
(\ g' gmax lmax list
-> if list == [] then
gmax
else
g' (max gmax lmax + head list) (max 0 lmax + head list) tail list)
Failed, modules loaded: none.
Changing from f (y y f) to f (y f) just gives
C:\maxsubseq.hs:11:29:
Couldn't match expected type `[Int] -> Int'
with actual type `[Int]'
Expected type: (([Int] -> Int) -> t1 -> t0) -> t2 -> t0
Actual type: ([Int] -> Int) -> t1 -> t0
In the first argument of `y', namely `f'
In the first argument of `f', namely `(y f)'
Failed, modules loaded: none.
I've tried taking a different approach by just defining the combinator externally, however this still isn't working and doesn't really meet my challenge to do it in one expression.
y f = f (y f)
msss' :: [Int] -> Int
msss' = y (\g' gmax lmax list -> if list == []
then gmax
else g' (max gmax lmax + head list)
(max 0 lmax + head list)
tail list)
Can you spot what's wrong with what I'm doing? I'm at a loss. The complaining about constructing infinite types really ticks me off because I though Haskell was all about that sort of thing. It has infinite data structures, so why the problem with infinite types? I suspect it has something to do with that paradox which showed untyped lambda calculus is inconsistent. I'm not sure though. Would be good if someone could clarify.
Also, I'm under the impression that recursion can always be represented with the fold functions. Can anyone show me how I could do it by just using a fold? The requirement that the code be a single expression still stands though.
You cannot define the Y combinator like that in Haskell. As you noticed, that results in an infinite type. Fortunately, it is already available in Data.Function as fix, where it's defined using a let binding:
fix f = let x = f x in x
Because the Y combinator needs infinite types, you'll need workarounds like this one.
But I'd write your msss function as a one-liner like this:
msss = fst . foldr (\x (gmax, lmax) -> let g = max (lmax + x) in (g gmax, g 0)) (0, 0)
Well let's think about it for a minute. What type does this lambda expression have?
(\y f x -> f (y y f) x)
Well f is a function (a -> b) -> a -> b, and x is some value b. What does that make y? Well given what we just said about f,
(y y f) :: (a -> b)
Also, since we are applying this expression to itself, we know that y has the same type as the entire expression. This is the part where I get a little bit stumped.
So y is some magical higher-order function. And it takes two functions as input. So it's sort of like y :: f1 -> f2 -> f3. f2 has the form of f, and f3 has the result type mentioned above.
y :: f1 -> ((a -> b) -> a -> b) -> (a -> b)
The question is...what is f1? Well, it has to be the same as the type of y. Do you see how this is getting beyond the power of Haskell's type system? The type is defined in terms of itself.
f1 = f1 -> ((a -> b) -> a -> b) -> (a -> b)
If you want a self-contained "one-liner", then take hammar's suggestion instead:
msss' = (\f -> let x = f x in x)
(\g' gmax lmax list -> case list of
[] -> gmax
(x:xs) -> g' (max gmax lmax + x) (max 0 lmax + x) xs
) 0 0
Although imho if max is allowable, then fix from Data.Function should be allowable as well. Unless you are in some Prelude-only contest.

Resources