foldr returning a list in Haskell - haskell

I'm reading this guide and understand how foldr works when we return a number.
sum' :: (Num a) => [a] -> a
sum' xs = foldl (\acc x -> acc + x) 0 xs
ghci> sum' [3,5,2,1]
11
Now I need foldr to return a list, and I can't run this code.
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldr (\x acc -> f x : acc) [] xs
I don't know what f should be.

Maybe this helps:
map' succ [1,2,3]
= foldr (\x acc -> succ x : acc) [] [1,2,3]
= foldr (\x acc -> succ x : acc) [] [1,2,3]
= (\x acc -> succ x : acc) 1 (foldr (\x acc -> succ x : acc) [] [2,3])
= succ x : acc where x=1 ; acc=foldr (\x acc -> succ x : acc) [] [2,3]
= succ 1 : foldr (\x acc -> succ x : acc) [] [2,3]
= succ 1 : (\x acc -> succ x : acc) 2 (foldr (\x acc -> succ x : acc) [] [3])
= succ 1 : succ 2 : foldr (\x acc -> succ x : acc) [] [3]
= succ 1 : succ 2 : (\x acc -> succ x : acc) 3 (foldr (\x acc -> succ x : acc) [] [])
= succ 1 : succ 2 : succ 3 : foldr (\x acc -> succ x : acc) [] []
= succ 1 : succ 2 : succ 3 : []
= 2 : 3 : 4 : []
= [2,3,4]

Look at the type:
map' :: (a -> b) -> [a] -> [b]
map' f xs = ys where ys = ...
f is a function of type a -> b:
f :: a -> b
f x = y where y = ...
meaning, given an x of type a, it produces a y of type b. So map' f has a type [a] -> [b],
map' :: (a -> b) -> [a] -> [b]
map' f xs = ys where ys = ...
map' f :: [a] -> [b]
that is, given a list xs of type [a], it produces a list ys of type [b].
So whatever f you're using, it must correspond to the list xs with which you intend to use map' f: it must accept elements of xs as arguments.

Related

How could I filter for many conditions in a list in Haskell?

the function definition is already given
filterMany :: [a -> Bool] -> [a] -> [a]
filterMany (f:fs) [] = []
filterMany (f:fs) (x)
| filter (f) x == True = x : filter (fs) x
| otherwise = filter (fs) x
the output should be:
filterMany [even, odd] [1..10] == []
filterMany [even, (\x -> x `mod` 4 /= 0)] [1..10] == [2,6,10]
filterMany [(<7), (>3), odd] [1..20] == [5]
You can make use of all :: (a -> Bool) -> [a] -> Bool here to check if all conditions are met. We thus can implement this with:
filterMany :: Foldable f => f (a -> Bool) -> [a] -> [a]
filterMany fs = filter (\x -> all ($ x) fs)
We here thus apply all predicates with parameter x by specifying all ($ x) fs. If all these predicates hold, then we retrain the element x.
For example:
Prelude> filterMany [even, odd] [1..10]
[]
Prelude> filterMany [even, (\x -> x `mod` 4 /= 0)] [1..10]
[2,6,10]
Prelude> filterMany [(<7), (>3), odd] [1..20]
[5]
Another way:
filterMany :: [a -> Bool] -> [a] -> [a]
filterMany [] (x:xs) = (x:xs)
filterMany (f:fs) (x:xs) = filter f (filterMany (fs) (x:xs))

Using foldr to define map (develop)

Having a hard time understanding fold... Is the expansion correct ? Also would appreciate any links, or analogies that would make fold more digestible.
foldMap :: (a -> b) -> [a] -> [b]
foldMap f [] = []
foldMap f xs = foldr (\x ys -> (f x) : ys) [] xs
b = (\x ys -> (f x):ys)
foldMap (*2) [1,2,3]
= b 1 (b 2 (foldr b [] 3))
= b 1 (b 2 (b 3 ( b [] [])))
= b 1 (b 2 ((*2 3) : []))
= b 1 ((*2 2) : (6 :[]))
= (* 2 1) : (4 : (6 : []))
= 2 : (4 : (6 : []))
First, let's not use the name foldMap since that's already a standard function different from map. If you want to re-implement an existing function with the same or similar semantics, convention is to give it the same name but either in a separate module, or with a prime ' appended to the name. Also, we can omit the empty-list case, since you can just pass that to the fold just as well:
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldr (\x ys -> f x : ys) [] xs
Now if you want to evaluate this function by hand, first just use the definition without inserting anything more:
map' (*2) [1,2,3,4]
≡ let f = (*2)
xs = [1,2,3,4]
in foldr (\x ys -> (f x) : ys) [] xs
≡ foldr (\x ys -> (*2) x : ys) [] [1,2,3,4]
Now just prettify a bit:
≡ foldr (\x ys -> x*2 : ys) [] [1,2,3,4]
Now to evaluate this through, you also need the definition of foldr. It's actually a bit different in GHC, but effectively
foldr _ z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
So with your example
...
≡ foldr (\x ys -> x*2 : ys) [] (1:[2,3,4])
≡ (\x ys -> x*2 : ys) 1 (foldr (\x ys -> x*2 : ys) [] [2,3,4])
Now we can perform a β-reduction:
≡ 1*2 : foldr (\x ys -> x*2 : ys) [] [2,3,4]
≡ 2 : foldr (\x ys -> x*2 : ys) [] [2,3,4]
...and repeat for the recursion.
foldr defines a family of equations,
foldr g n [] = n
foldr g n [x] = g x (foldr g n []) = g x n
foldr g n [x,y] = g x (foldr g n [y]) = g x (g y n)
foldr g n [x,y,z] = g x (foldr g n [y,z]) = g x (g y (g z n))
----- r ---------
and so on. g is a reducer function,
g x r = ....
accepting as x an element of the input list, and as r the result of recursively processing the rest of the input list (as can be seen in the equations).
map, on the other hand, defines a family of equations
map f [] = []
map f [x] = [f x] = (:) (f x) [] = ((:) . f) x []
map f [x,y] = [f x, f y] = ((:) . f) x (((:) . f) y [])
map f [x,y,z] = [f x, f y, f z] = ((:) . f) x (((:) . f) y (((:) . f) z []))
= (:) (f x) ( (:) (f y) ( (:) (f z) []))
The two families simply exactly match with
g = ((:) . f) = (\x -> (:) (f x)) = (\x r -> f x : r)
and n = [], and thus
foldr ((:) . f) [] xs == map f xs
We can prove this rigorously by mathematical induction on the input list's length, following the defining laws of foldr,
foldr g n [] = []
foldr g n (x:xs) = g x (foldr g n xs)
which are the basis for the equations at the top of this post.
Modern Haskell has Fodable type class with its basic fold following the laws of
fold(<>,n) [] = n
fold(<>,n) (xs ++ ys) = fold(<>,n) xs <> fold(<>,n) ys
and the map is naturally defined in its terms as
map f xs = foldMap (\x -> [f x]) xs
turning [x, y, z, ...] into [f x] ++ [f y] ++ [f z] ++ ..., since for lists (<>) == (++). This follows from the equivalence
f x : ys == [f x] ++ ys
This also lets us define filter along the same lines easily, as
filter p xs = foldMap (\x -> [x | p x]) xs
To your specific question, the expansion is correct, except that (*2 x) should be written as ((*2) x), which is the same as (x * 2). (* 2 x) is not a valid Haskell (though valid Lisp :) ).
Functions like (*2) are known as "operator sections" -- the missing argument goes into the empty slot: (* 2) 3 = (3 * 2) = (3 *) 2 = (*) 3 2.
You also asked for some links: see e.g. this, this and this.

Recursive definitions of scanl and scanr in Haskell

I have searched but cannot find simple definitions of the functions scanr and scanl, only explanations that they show the intermediate calculations of the functions foldr and foldl (respectively).
I have written a recursive definition for scanl, based on the foldl property foldl f y (x:xs) = foldl f (f y x) xs:
scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' f x [] = [x]
scanl' f x (y:ys) = x : scanl' f (f x y) ys
This seems to work. However, there is a type error when I try to apply this analogy with the foldr property foldr f y (x:xs) = f x (foldr f y xs):
scanr' :: (a -> b -> b) -> b -> [a] -> [b]
scanr' _ x [] = [x]
scanr' f x (y:ys) = y : f x (scanr' f x ys)
This fails as the second input for f needs to be a b not a [b]. However, I am unsure how to do this while also recursing on scanr'.
To compute
result = scanr' f x (y:ys)
you must have computed
partialResult = scanr' f x ys
after which you get
result = (y `f` head partialResult) : partialResult
The complete implementation is
scanr' _ x [] = [x]
scanr' f x (y:ys) = (y `f` head partialResult) : partialResult
where partialResult = scanr' f x ys
scanl1 (\acc x -> if x > acc then x else acc)[3,4,5,3,7,9,2,1]
from Learn You A Haskell seems to have only two arguments: the function and the list. Yet it works. It even works if you write it as:
scanl1 (\x acc -> if x > acc then x else acc)[3,4,5,3,7,9,2,1]
Slightly puzzling why works.

Haskell foldr unexpectedly gives an error

Why does writing map using foldr this way
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldr (\x acc -> f x : acc) []
give the following error?
test.hs:2:13: error:
• Couldn't match expected type ‘[b]’ with actual type ‘t0 a -> [b]’
• Probable cause: ‘foldr’ is applied to too few arguments
In the expression: foldr (\ x acc -> f x : acc) []
In an equation for ‘map'’:
map' f xs = foldr (\ x acc -> f x : acc) []
• Relevant bindings include
xs :: [a] (bound at test.hs:2:8)
f :: a -> b (bound at test.hs:2:6)
map' :: (a -> b) -> [a] -> [b] (bound at test.hs:2:1)
|
2 | map' f xs = foldr (\x acc -> f x : acc) []
| ^^^^^^^^^^^^^^^^^^^^^^^^^
You don't use xs. You can either write:
map' f xs = foldr (\x acc -> f x : acc) [] xs
or
map' f = foldr (\x acc -> f x : acc) []

sum3 with zipWith3 in Haskell

I'm trying to write a Haskell function that would take three lists and return a list of sums of their elements.
Currently I'm trying to do it using zipWith3:
sum3 :: Num a => [a] -> [a] -> [a] -> [a]
sum3 xs ys zs = zipWith3 (\x y z -> x+y+z) xs ys zs
The problem is it only works for lists of equal lengths. But I wish sum3 to work with lists of unequal lengths, so that
sum3 [1,2,3] [4,5] [6]
would return
[11,7,3]
I think that I should redefine zipWith3 to work with lists of unequal lengths, but can't figure out how to do it (I suspect that I have to exhaust all possibilities of empty lists).
Is there a solution?
a nice trick is to use transpose:
import Data.List (transpose)
sum3 :: Num a => [a] -> [a] -> [a] -> [a]
sum3 as bs cs = map sum $ transpose [as,bs,cs]
because obviously you want to sum up the columns ;)
> sum3 [1,2,3] [4,5] [6]
[11,7,3]
I've seen this sort of question before, here: Zip with default value instead of dropping values? My answer to that question also pertains here.
The ZipList applicative
Lists with a designated padding element are applicative (the applicative grown from the 1 and max monoid structure on positive numbers).
data Padme m = (:-) {padded :: [m], padder :: m} deriving (Show, Eq)
instance Applicative Padme where
pure = ([] :-)
(fs :- f) <*> (ss :- s) = zapp fs ss :- f s where
zapp [] ss = map f ss
zapp fs [] = map ($ s) fs
zapp (f : fs) (s : ss) = f s : zapp fs ss
-- and for those of you who don't have DefaultSuperclassInstances
instance Functor Padme where fmap = (<*>) . pure
Now we can pack up lists of numbers with their appropriate padding
pad0 :: [Int] -> Padme Int
pad0 = (:- 0)
And that gives
padded ((\x y z -> x+y+z) <$> pad0 [1,2,3] <*> pad0 [4,5] <*> pad0 [6])
= [11,7,3]
Or, with the Idiom Brackets that aren't available, you vould write
padded (|pad0 [1,2,3] + (|pad0 [4,5] + pad0 6|)|)
meaning the same.
Applicative gives you a good way to bottle the essential idea of "padding" that this problem demands.
Well if you must use zipWith3:
sum3 :: Num a => [a] -> [a] -> [a] -> [a]
sum3 xs ys zs = zipWith3 (\x y z -> x + y + z) xs' ys' zs'
where
xs' = pad nx xs; nx = length xs
ys' = pad ny ys; ny = length ys
zs' = pad nz zs; nz = length zs
n = nx `max` ny `max` nz
pad n' = (++ replicate (n-n') 0)
Some samples:
*> sum3 [] [] []
[]
*> sum3 [0] [] []
[0]
*> sum3 [1] [1] [2, 2]
[4,2]
*> sum3 [1,2,3] [4,5] [6]
[11,7,3]
but I'd recommend going with Carsten's transpose based implementation.
Perhaps you could get away with something that is almost zipWith3 but which relies on Default to generate empty values on the fly if one of the lists runs out of elements:
import Data.Default
zipWith3' :: (Default a, Default b, Default c)
=> ( a -> b -> c -> r )
-> ([a] -> [b] -> [c] -> [r])
zipWith3' f = go where
go [] [] [] = []
go (x:xs) (y:ys) (z:zs) = f x y z : go xs ys zs
go [] ys zs = go [def] ys zs
go xs [] zs = go xs [def] zs
go xs ys [] = go xs ys [def]
and 'sum3'`:
sum3' :: (Default a, Num a) => [a] -> [a] -> [a] -> [a]
sum3' = zipWith3' (\x y z -> x + y + z)
One could generalize zipWith so to handle the excess tails, instead of discarding them silently.
zipWithK :: (a->b->c) -> ([a]->[c]) -> ([b]->[c]) -> [a] -> [b] -> [c]
zipWithK fab fa fb = go
where go [] [] = []
go as [] = fa as
go [] bs = fb bs
go (a:as) (b:bs) = fab a b : go as bs
The original zipWith is then
zipWith' :: (a->b->c) -> [a] -> [b] -> [c]
zipWith' f = zipWithK f (const []) (const [])
Back to the original problem,
sum2 :: Num a => [a] -> [a] -> [a]
sum2 = zipWithK (+) id id
sum3 :: Num a => [a] -> [a] -> [a] -> [a]
sum3 xs ys zs = xs `sum2` ys `sum2` zs
This is my solution:
sumLists :: Num a => [a] -> [a] -> [a]
sumLists (x : xs) (y : ys) = (x + y) : sumLists xs ys
sumLists _ _ = []
sum3 :: (Num a, Enum a) => [a] -> [a] -> [a] -> [a]
sum3 xs ys zs = foldr sumLists defaultList (map addElems list)
where list = [xs, ys, zs]
defaultList = [] ++ [0, 0 ..]
maxLength = maximum $ map length list
addElems = \x -> if length x < maxLength then x ++ [0, 0 ..] else x

Resources