There is some case where I don't understand how foldr and foldl are used in function.
Here is a couple of example, I then explain why I don't understand them:
-- Two implementation of filter and map
map' f = foldr (\x acc -> (f x):acc) []
map'' f xs = foldl (\acc x -> acc ++ [(f x)]) [] xs
filter' f xs = foldr(\x acc -> if(f x) then x:acc else acc) [] xs
filter'' f = foldl(\acc x -> if(f x) then acc++[x] else acc) []
Why does map'' makes the use of xs but non map'? Shouldn't map' need a list for the list comprehension formula as well?
Same case for filter' vs filter''.
Here is an implementation which insert elements in a sorted sequence:
insert e [] = [e]
insert e (x:xs)
| e > x = x: insert e xs
| otherwise = e:x:xs
sortInsertion xs = foldr insert [] xs
sortInsertion'' xs = foldl (flip insert) [] xs
Why are the argument for insert flipped in sortInsertion ([] xs) (empty list and list) compare to the definition of insert(e []) (element and empty list)
Why does map'' makes the use of xs but non map'? Shouldn't map' need a list for the list comprehension formula as well? Same case for filter' vs filter''.
This is called “eta-reduction” and it’s a common way of omitting redundant parameter names (“point-free style”). Essentially whenever you have a function whose body is just an application of a function to its argument, you can reduce away the argument:
add :: Int -> Int -> Int
add x y = x + y
-- “To add x and y, call (+) on x and y.”
add :: (Int) -> (Int) -> (Int)
add x y = ((+) x) y
-- “To add x, call (+) on x.”
add :: (Int) -> (Int -> Int)
add x = (+) x
-- “To add, call (+).”
add :: (Int -> Int -> Int)
add = (+)
More precisely, if you have f x = g x where x does not appear in g, then you can write f = g.
A common mistake is then wondering why f x = g . h x can’t be written as f = g . h. It doesn’t fit the pattern because the (.) operator is the top-level expression in the body of f: it’s actually f x = (.) g (h x). You can write this as f x = (((.) g) . h) x and then reduce it to f = (.) g . h or f = fmap g . h using the Functor instance for ->, but this isn’t considered very readable.
Why are the argument for insert flipped in sortInsertion
The functional parameters of foldr and foldl have different argument order:
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
Or, with more verbose type variable names:
foldr
:: (Foldable container)
=> (element -> accumulator -> accumulator)
-> accumulator -> container element -> accumulator
foldl
:: (Foldable container)
=> (accumulator -> element -> accumulator)
-> accumulator -> container element -> accumulator
This is just a mnemonic for the direction that the fold associates:
foldr f z [a, b, c, d]
==
f a (f b (f c (f d z))) -- accumulator on the right (second argument)
foldl f z [a, b, c, d]
==
f (f (f (f z a) b) c) d -- accumulator on the left (first argument)
That is partial function application.
map' f = foldr (\x acc -> (f x):acc) []
is just the same as
map' f xs = foldr (\x acc -> (f x):acc) [] xs
if you omit xs on both sides.
However, beside this explanation, I think you need a beginner book for Haskell. Consider LYAH.
Related
My goal here was to convert a (int * int) list to an int list. This is what I did:
let tuples_list_to_list l =
let rec aux_tuples_to_list acc l =
match l with
| [] -> acc
| x :: tl -> aux_tuples_to_list (fst x :: snd x :: acc) tl in
aux_tuples_to_list [] l
I was wondering if there was a more "elegant" even though this is subjective or at least better, way to write my function. I was thinking about using List.map or List.fold_left but I was having issues figuring out I could use those two functions to do the same thing I did. Basically, I think it would be possible to have a one-liner instead of the whole function I wrote.
What do you think? Thanks
This task is suited for List.concat_map (also known as "flat map" in some other languages):
(* List.concat_map : ('a -> 'b list) -> 'a list -> 'b list *)
let tuples_list_to_list l =
List.concat_map (fun (x, y) -> [x; y]) l
You can use List.fold_left, but you'll have to reverse the result at the end as the list is constructed in reverse order:
let tuples_list_to_list l =
List.rev (List.fold_left (fun acc (x, y) -> y :: x :: acc) [] l)
You can also deconstruct the tuple values in the pattern matching instead of using fst and snd (This version, unlike yours, gives a result list with the numbers in the same order as the orignal):
let tuples_list_to_list l =
let rec aux_tuples_to_list acc l =
match l with
| [] -> List.rev acc
| (x, y) :: tl -> aux_tuples_to_list (y :: x :: acc) tl in
aux_tuples_to_list [] l
Yet Another Option is using List.fold_right, which avoids the need to reverse the accumulator list at the end at the cost of not being tail recursive:
let tuples_list_to_list l =
List.fold_right (fun (x, y) acc -> x :: y :: acc) l [];;
I wrote a filter function:
f :: (a -> Bool) -> [a] -> [a]
f p xs = case xs of
[] -> []
x : xs' -> if p x
then x : f p xs'
else f p xs'
To understand bind, I want to implement this using bind.
What I was thinking about:
f p xs = xs >>= (\x xs -> if p x then x : f p xs else f p xs)
But I get this error:
* Couldn't match expected type `[a]' with actual type `[a] -> [a]'
* The lambda expression `\ x xs -> ...' has two arguments,
but its type `a -> [a]' has only one
In the second argument of `(>>=)', namely
`(\ x xs -> if p x then x : f p xs else f p xs)'
In the expression:
xs >>= (\ x xs -> if p x then x : f p xs else f p xs)
* Relevant bindings include
xs :: [a] (bound at <interactive>:104:5)
p :: a -> Bool (bound at <interactive>:104:3)
f :: (a -> Bool) -> [a] -> [a] (bound at <interactive>:104:1)
Successfully did it using foldr:
f p xs = foldr (\x xs -> if p x then x : f p xs else f p xs) [] xs
What's going wrong?
To understand bind, i want to implement this as bind.
There is no bind here. The bind is added in case of a do expression. The above is not a do-expression, so there is no bind here.
You can however write this with bind, like:
f p xs = xs >>= \x -> if p x then [x] else []
but this is not a literal mapping of the original function, we simply make use of the instance Monad [] implementation here. Nevertheless, your f is just filter :: (a -> Bool) -> [a] -> [a] here.
To understand bind, first implement the no-op:
id_list xs = concat [ [x] | x <- xs ] = [ y | x <- xs, y <- [x ] ]
Now for the filter, augment it as
filter p xs = concat [ [x | p x] | x <- xs ] = [ y | x <- xs, y <- [x | p x] ]
How is this code using bind, you ask? If we're using MonadComprehensions, it does.
The explicit do-notation re-write is straightforward:
id_list xs = do { x <- xs ; y <- [ x ] ; return y }
filter p xs = do { x <- xs ; y <- [ x | p x] ; return y }
And of course, for lists,
[x] == return x
[x | p x] == if p x then return x else mzero
mzero == []
concat == join
This brings us back to an explicitly recursive way to code filter as
filter p [] = []
filter p (x:xs) = [x | p x] ++ filter p xs
With bind, we think in terms of transforming each element of the list individually, into the list of results (none, one, or several) for that one input element. Your foldr-based code breaks this.
So, the code itself is just
filter_bind p xs = xs >>= (\x -> [x | p x])
because we have
xs >>= f == join (fmap f xs)
== concat (map f xs)
== concat [ f x | x <- xs ]
== foldr (++) []
[ f x | x <- xs ]
with the last snippet corresponding to the explicitly recursive definition above.
See also
How does the List monad work in this example?
Haskell Monad - How does Monad on list work?
etc.
I am attempting to implement the zipWith function via the zip and map functions, but I am getting an error that reads: "error: parse error on input '::' My code is below and and I am unsure of what I have done wrong
zipWith` :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith` f x y = zip x $ map f y
You have to use ' symbol and not ` ; then, to combine the function you need to use uncurry:
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f xs ys = map (uncurry f) (zip xs ys)
why is that, well the type of zip is:
zip :: [a] -> [b] -> [(a, b)]
but the function f is f :: (a -> b -> c), so, with the help of uncurry,
uncurry :: (a -> b -> c) -> (a, b) -> c
you can map the function f into the [(a, b)], transforming it into [c].
As Damian points out, zipWith` doesn't work with the trailing backtick -- the backtick has a special meaning in Haskell. Rename it to zipWith'.
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
Then of course you have to actually write the solution. With explicit recursion you've got
zipWith' _ _ [] = []
zipWith' _ [] _ = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
but using map and zip you could apply it like this:
zipWith' f xs ys = map (\(x,y) -> f x y) . zip xs $ ys
or more easily-read:
zipWith' f xs ys = map (\(x,y) -> f x y) zipped
where zipped = zip xs ys
In my problem i have list of lists, and i want to find list of lists being selectors (selector - list containing exactly one element from each list), satisfying special condition.
The code to generate all selectors would look like:
selectors :: [[a]] -> [[a]]
selectors [] = [[]]
selectors (y:ys) = [ (x:xs) | x <- y, xs <- selectors ys]
If i wanted to add some extra condition this would be like
selectors :: [[a]] -> ([a] -> Bool) -> [[a]]
selectors [] _ = [[]]
selectors (y:ys) f = [ (x:xs) | x <- y, xs <- selectors ys f, f xs]
However in my problem, i need the condition to be dependable on element being candidate for a list, and what's in list i currently build. So this would be something like:
selectors :: [[a]] -> ( a-> [a] -> Bool) -> [[a]]
selectors [] _ = [[]]
selectors (y:ys) f = [ (x:xs) | x <- y, xs <- selectors ys f, f x xs]
And this is working very slow, because at first the recursion goes in very deeply and real work starts from there, whereas this would be MUCH faster if building list was going from left, so whenever i try to add new element to my list and i know this cannot be added so i'd just try to add new element. How can i make this work this way?
You can change the order of some searches by commuting the loop bodies.
for i in foo foo j in bar
for j in bar versus foo i in foo
do(i, j) do(i, j)
The same effect can be achieved in list comprehension syntax. For the given example, it might be
[ (x:xs) | x <- y, xs <- selectors ys f, f x xs ]
-- versus
[ (x:xs) | xs <- selectors ys f, x <- y, f x xs ]
If we're only considering the result as a set of values (i.e. the order is immaterial) then the values are identical. Regarded as a set, the only rules considering order of list comprehension clauses are that referenced variables must be bound in clauses left of their reference site.
Let's desugar this notation a bit to see the mechanics at work in higher fidelity.
List comprehensions are (almost) equivalent to do-notation in the list monad. Without necessarily diving into what monads are, I'll claim that our list comprehension desugars like this
-- [ (x:xs) | x <- y, xs <- selectors ys f, f x xs ]
-- becomes...
do x <- y
xs <- selectors ys f
guard (f x xs)
return (x:xs)
The translation should be obvious—each generator clause containing (<-) becomes a do-syntax binding form. Each guard clause becomes a do-notation form using the (perfectly normal) function guard :: Bool -> [()]. Finally, the translation preserves order.
But now, do-notation is just syntax sugar itself! It desugars to a series of function applications. Again, to not dive into the meaning of monads, I'll just do this transformation exactly.
-- [ (x:xs) | x <- y, xs <- selectors ys f, f x xs ]
-- becomes...
y >>= (\x -> selectors ys f >>= (\xs -> guard (f x xs) >> return (x:xs)))
In particular, each generator line like x <- E becomes E >>= (\x -> ...) where the ... corresponds to the translation of the remainder of the do block. Lines like E without binding arrows translate to E >> .... We can even simplify this one level further by noting that E >> F is nothing more than E >>= (\_ -> F) so that ultimately we have
y >>= (\x -> selectors ys f >>= (\xs -> guard (f x xs) >>= (\_ -> return (x:xs))))
And as a final step, we can translate the (>>=), guard, and return functions to the format they take for the list monad. In particular ls >>= f is equal to concat (map f ls) and return x = [x]. It's actually convenient to write (>>=) in a prefix instead of infix form, as well, so we'll call it forl :: [a] -> (a -> [b]) -> [b].
The function guard is a little strange. It looks like guard b = if b then [()] else []. We'll see how it works in a moment.
forl y $ \x ->
forl (selectors ys f) $ \xs ->
forl (guard (f x xs)) $ \_ ->
[x:xs]
Now this is a full translation. If we can understand this then we've understood the mechanics of the list comprehension. For comparison, this is how the list comprehension desugars when we switch the order of the generator clauses
forl y $ \x -> forl (selectors ys f) $ \xs ->
forl (selectors ys f) $ \xs -> forl y $ \x ->
forl (guard (f x xs)) $ \_ -> forl (guard (f x xs)) $ \_ ->
[x:xs] [x:xs]
which looks very similar to the imperative example given at the beginning. Let's show that it's actually identical.
First, we can dispatch how forl (guard (f x xs)) $ \_ -> [x:xs] works. We'll just inline the definition of guard and then forl
forl (if (f x xs) then [()] else []) (\_ -> [x:xs])
concat (map (\_ -> [x:xs]) (if (f x xs) then [()] else []))
We can "lift" the if out of the inside by noting that once we've wrapped the whole thing in an outer lift, the value of (f x xs) is fixed in both the then and else branches.
if (f x xs)
then concat (map (\_ -> [x:xs]) [()]
else concat (map (\_ -> [x:xs]) []
And finally, we can inline the maps and then the concats
if f x xs
then concat [(\_ -> [x:xs]) ()]
then concat []
if f x xs then [x:xs] else []
forl y $ \x -> forl (selectors ys f) $ \xs ->
forl (selectors ys f) $ \xs -> forl y $ \x ->
if f x xs then [x:xs] else [] if f x xs then [x:xs] else []
And now it ought to be increasingly clear how these "for" loops work. They loop over a body and produce a list of the results. Since we expect that the body will also be a forl loop, we have to anticipate that the value in the body is a list itself—this we flatten that extra layer of lists using concat.
How to implement insert using foldr in haskell.
I tried:
insert'' :: Ord a => a -> [a] -> [a]
insert'' e xs = foldr (\x -> \y -> if x<y then x:y else y:x) [e] xs
No dice.
I have to insert element e in list so that it goes before first element that is larger or equal to it.
Example:
insert'' 2.5 [1,2,3] => [1.0,2.0,2.5,3.0]
insert'' 2.5 [3,2,1] => [2.5,3.0,2.0,1.0]
insert'' 2 [1,2,1] => [1,2,2,1]
In last example first 2 is inserted one.
EDIT:
Thanks #Lee.
I have this now:
insert'' :: Ord a => a -> [a] -> [a]
insert'' e xs = insert2 e (reverse xs)
insert2 e = reverse . snd . foldr (\i (done, l) -> if (done == False) && (vj e i) then (True, e:i:l) else (done, i:l)) (False, [])
where vj e i = e<=i
But for this is not working:
insert'' 2 [1,3,2,3,3] => [1,3,2,2,3,3]
insert'' 2 [1,3,3,4] => [1,3,2,3,4]
insert'' 2 [4,3,2,1] => [4,2,3,2,1]
SOLUTION:
insert'' :: Ord a => a -> [a] -> [a]
insert'' x xs = foldr pom poc xs False
where
pom y f je
| je || x > y = y : f je
| otherwise = x : y : f True
poc True = []
poc _ = [x]
Thanks #Pedro Rodrigues (It just nedded to change x>=y to x>y.)
(How to mark this as answered?)
You need paramorphism for that:
para :: (a -> [a] -> r -> r) -> r -> [a] -> r
foldr :: (a -> r -> r) -> r -> [a] -> r
para c n (x : xs) = c x xs (para c n xs)
foldr c n (x : xs) = c x (foldr c n xs)
para _ n [] = n
foldr _ n [] = n
with it,
insert v xs = para (\x xs r -> if v <= x then (v:x:xs) else (x:r)) [v] xs
We can imitate paramorphisms with foldr over init . tails, as can be seen here: Need to partition a list into lists based on breaks in ascending order of elements (Haskell).
Thus the solution is
import Data.List (tails)
insert v xs = foldr g [v] (init $ tails xs)
where
g xs#(x:_) r | v <= x = v : xs
| otherwise = x : r
Another way to encode paramorphisms is by a chain of functions, as seen in the answer by Pedro Rodrigues, to arrange for the left-to-right information flow while passing a second copy of the input list itself as an argument (replicating the effect of tails):
insert v xs = foldr g (\ _ -> [v]) xs xs
where
g x r xs | v > x = x : r (tail xs) -- xs =#= (x:_)
| otherwise = v : xs
-- visual aid to how this works, for a list [a,b,c,d]:
-- g a (g b (g c (g d (\ _ -> [v])))) [a,b,c,d]
Unlike the version in his answer, this does not copy the rest of the list structure after the insertion point (which is possible because of paramorphism's "eating the cake and having it too").
Here's my take at it:
insert :: Ord a => a -> [a] -> [a]
insert x xs = foldr aux initial xs False
where
aux y f done
| done || x > y = y : f done
| otherwise = x : y : f True
initial True = []
initial _ = [x]
However IMHO using foldr is not the best fit for this problem, and for me the following solution is easier to understand:
insert :: Int -> [Int] -> [Int]
insert x [] = [x]
insert x z#(y : ys)
| x <= y = x : z
| otherwise = y : insert x ys
I suppose fold isn't handy here. It always processes all elements of list, but you need to stop then first occurence was found.
Of course it is possible, but you probable don't want to use this:
insert' l a = snd $ foldl (\(done, l') b -> if done then (True, l'++[b]) else if a<b then (False, l'++[b]) else (True, l'++[a,b])) (False, []) l