Understanding Haskell function in a lambda calculus way - haskell

Im trying to define the filter function. Based on the function's definition, the filter' function is a function (say help function to differ from the main filter' function) that takes in a function and a list to give a list. The help function takes in a variable and gives back a Bool value. But according the line 4, the help function evaluates a along with [x] to give a Bool Value which then finally gives back a list.
So can I understand the help function as a function that takes in a and [a] to give a Bool value. The main filter' function then takes in this Bool value to give back a list?
Im aware that the function's definition does not suggest this but it's kinda logical based on the code. Thanks
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' a (x:xs)
| a x == True = x:filter' a xs
| otherwise = filter' a xs

I think this will be clearer if we give the function of type a -> Bool a name other than a.
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' f (x:xs)
| f x == True = x:filter' f xs
| otherwise = filter' f xs
Now f has type a -> Bool, x :: a, and xs :: [a].
I like your description of (a -> Bool) -> [a] -> [a] as "takes in a function and a list to give a list". The recursive calls to filter' in lines 4 & 5 have the same type. f is passed along unchanged. xs is a list of as, but it's one a shorter than the input list. There is only one function filter'. The definition of the function refers to itself - that's an essential part of what we mean by "recursive function".

You can use the syntax even more to aid your understanding:
filter' :: (a -> Bool) -> [a] -> [a]
filter' p [] = []
filter' p (x:xs)
| (p x) == True = x : ( filter' p xs )
| otherwise = ( filter' p xs )
Which is
filter' :: (a -> Bool) -> [a] -> [a]
filter' p [] = []
filter' p (x:xs)
| (p x) = x : ( filter' p xs )
| otherwise = ( filter' p xs )
Or translate it to the more basic constructs,
filter' :: (a -> Bool)
-> [a] -> [a]
filter' p = ( \ xs -> case xs of
{ [] -> []
; (x:ys) | p x -> x : ( filter' p ys )
; (x:ys) -> ( filter' p ys ) } )
" p" is for "predicate". It is used by filter' to test each x in the input xs, to decide whether to include that x or not in the output, according to the Boolean value that the testing has produced.
p is just passed around unchanged from one invocation of filter' to the next. This is usually coded away with the so called "worker-wrapper" transformation,
filter' :: (a -> Bool) -> [a] -> [a]
filter' p xs = go xs where
go [] = []
go (x:xs) | p x = x : go xs
| otherwise = go xs
Lastly, a simpler-looking definition could also be
filter' :: (a -> Bool) -> [a] -> [a]
filter' p xs = go xs where
go [] = []
go (x:xs) = [x | p x] ++ go xs
which corresponds nicely with the foldMap-based definition
filter' p = foldMap (\ x -> [x | p x])

Related

Insertion sort using tail recursion & first order function

I'd like to design an algorithm in Haskell using tail recursion and first order programming for insertion sort
I've came up with this solution
isort :: Ord a => [a] -> [a]
isort [] = []
isort [x] = [x]
isort ( x:xs ) = insert ( isort xs )
where insert [] = [x]
insert ( y:ys )
| x < y = x : y : ys
| otherwise = y : insert ys
But I'm not sure if it uses first order and tail recursion.
Can someone come up with an alternative solution using
tail recursion
first order programming
Thanks,
This is the simple version, not using tail recursion nor HOF
sort :: Ord a => [a] -> [a]
sort [] = []
sort [x] = [x]
sort (x:xs) = insert x (sort xs)
insert :: Ord a => a -> [a] -> [a]
insert x [] = [x]
insert x (y:ys) | x < y = x:y:ys
| otherwise = y:insert x ys
You can add an accumulator, that allows us to rewrite the sort using tail recursion:
sort' :: Ord a => [a] -> [a]
sort' xs = sortAcc xs []
sortAcc :: Ord a => [a] -> [a] -> [a]
sortAcc [] acc = acc
sortAcc (x:xs) acc = sortAcc xs (insert x acc)
insert is pretty nicely defined the way it is; but just for the purpose
of using higher order functions, we can define it like:
insert' :: Ord a => a -> [a] -> [a]
insert' x xs = menores ++ x:mayores
where (menores,mayores) = span (<x) xs
where the section (<x) is a function of type Ord a => a -> Bool passed to span.

Haskell error: Variable not in scope

I'm a bit new to Haskell but I've been working this problem for a couple hours with no luck.
I'm trying to implement something similar to a filter, except a predicate and list is passed to a function and it returns a tuple of two lists, one which is filtered by the predicate and one which is not.
divideList :: (a -> Bool) -> [a] -> ([a],[a])
divideList p xs = (f, nf) where
f = doFilter p xs
nf = doFilter (not . p) xs
doFilter :: (a -> Bool) -> [a] -> [a]
doFilter _ [] = []
doFilter p (x:xs) = [x | p x] ++ doFilter p xs
The second function, doFilter works properly. It applies the filter to its list and spits out the appropriate list. (i.e. If I just use doFilter (>3) [1,2,3,4,5,6] it will work properly)
My issue is with the first function. When I use divideList (>3) [1,2,3,4,5,6] I get a number of Variable not in scope errors. The errors are listed below:
AddListOperations.hs:20:23: error:
Variable not in scope: p :: a -> Bool
AddListOperations.hs:20:25: error: Variable not in scope: xs :: [a]
AddListOperations.hs:21:31: error:
Variable not in scope: p :: a -> Bool
AddListOperations.hs:21:34: error: Variable not in scope: xs :: [a]
Like I said, I have only been messing around with Haskell for a few days so let me know if I'm leaving out any important information.
Indent both f and nf:
divideList :: (a -> Bool) -> [a] -> ([a],[a])
divideList p xs = (f, nf) where
f = doFilter p xs
nf = doFilter (not . p) xs
After all, where would your where block stop?
By the way, divideList is partition from Data.List.
Thanks to Alec, I found that all I needed to do was indent the statements underneath where:
divideList :: (a -> Bool) -> [a] -> ([a],[a])
divideList p xs = (f, nf) where
f = doFilter p xs
nf = doFilter (not . p) xs

Prefix function as a predicate for filter function

Here is the type signature and the definition of the filter function from Learn You a Haskell for Great Good!:
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' p (x:xs)
| p x = x : filter' p xs
| otherwise = filter' p xs
An usage example in the book is with elem is as follows:
filter' (`elem` ['a'..'z']) "Hell0!"
Which returns:
"ell"
In this particular example, is there a possible way of using elem as a prefix function instead of an infix function as a predicate?
In a more general sense, is there a way to supply only the second parameter in order to partially apply a prefix function?
Thanks in advance for your help!
Either by creating a lambda (which will work for functions taking more than 2 parameters):
filter' (\a -> elem a ['a'..'z']) "Hell0!"
Or by using flip:
filter' (flip elem ['a'..'z']) "Hell0!"
Sounds like you're after flip :: (a -> b -> c) -> b -> a -> c, which is in the prelude.
It can be implemented as flip f = \b a -> f a b.

Haskell multifilter

I want to filter a list by predicates curried from another list.
For instance:
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter _ _ [] = []
multifilter _ [] _ = []
multifilter f (x:xs) ys = (filter (f x) ys) ++ (multifilter f xs ys)
With usage such as:
prelude> multifilter (==) [1,2,3] [5,3,2]
[2,3]
Is there a standard way to do this?
You can use intersectBy:
λ> :t intersectBy
intersectBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
λ> intersectBy (==) [1,2,3] [5,3,2]
[2,3]
You can use hoogle to search functions using type signature and finding them.
Note: This answer implements the specification expressed by the words and example in the question, rather than the different one given by the implementation of multifilter there. For the latter possibility, see gallais' answer.
Sibi's answer shows how you should actually do it. In any case, it is instructive to consider how you might write your function using filter. To begin with, we can establish two facts about it:
multifilter can be expressed directly as filter pred for some appropriate choice of pred. Given a fixed "predicate list", whether an element of the list you are multifiltering will be in the result only depends on the value of that element.
In multifilter f xs ys, the list you are filtering is xs, and the "predicate list" is ys. Were it not so, you would get [3,2] rather than [2,3] in your (quite well-chosen) example.
So we have:
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter f xs ys = filter pred xs
where
pred = undefined -- TODO
All we need to do is implementing pred. Given an element x, pred should produce True if, for some element y of ys, f x y is true. We can conveniently express that using any:
pred x = any (\y -> f x y) ys
-- Or, with less line noise:
pred x = any (f x) ys
Therefore, multifilter becomes...
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter f xs ys = filter pred xs
where
pred x = any (f x) ys
-- Or, more compactly:
multifilter :: (a -> a -> Bool) -> [a] -> [a] -> [a]
multifilter f xs ys = filter (\x -> any (f x) ys) xs
... which is essentially equivalent to intersectBy, as you can see by looking at intersectBy's implementation.
A third option is to use a list comprehension:
multifilter rel xs ys = [ x | x <- xs, y <- ys, x `rel` y ]
or, if you want partial application:
multifilter p xs ys = [ x | x <- xs, let f = p x, y <- ys, f y ]
If you want to use filter,
relate rel xs ys = filter (uncurry rel) $ liftM2 (,) xs ys
(and throw in map fst)
The answer you have accepted provides a function distinct from the one defined in your post: it retains elements from xs when yours retains elements from ys. You can spot this mistake by using a more general type for multifilter:
multifilter :: (a -> b -> Bool) -> [a] -> [b] -> [b]
Now, this can be implemented following the specification described in your post like so:
multifilter p xs ys = fmap snd
$ filter (uncurry p)
$ concatMap (\ x -> fmap (x,) ys) xs
If you don't mind retaining the values in the order they are in in ys then you can have an even simpler definition:
multifilter' :: (a -> b -> Bool) -> [a] -> [b] -> [b]
multifilter' p xs = filter (flip any xs . flip p)
Simply use Hoogle to find it out via the signature (a -> a -> Bool) -> [a] -> [a] -> [a]
https://www.haskell.org/hoogle/?hoogle=%28a+-%3E+a+-%3E+Bool%29+-%3E+%5Ba%5D+-%3E+%5Ba%5D+-%3E+%5Ba%5D
yields intersectBy:
intersectBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]

How would you define map and filter using foldr in Haskell?

I'm doing a bit of self study on functional languages (currently using Haskell). I came across a Haskell based assignment which requires defining map and filter in terms of foldr. For the life of me I'm not fully understanding how to go about this.
For example when I define a map function like:
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = foldr (\x xs -> (f x):xs) [] xs
I don't know why the first element of the list is always ignored. Meaning that:
map' (*2) [1,2,3,4]
results in [4,6,8] instead of [2,4,6,8]
Similarly, my filter' function:
filter' :: (a -> Bool) -> [a] -> [a]
filter' p [] = []
filter' p (x:xs) = foldr (\x xs -> if p x then x:xs else xs ) [] xs
when run as:
filter' even [2,3,4,5,6]
results in [4,6] instead of [2,4,6]
Why would this be the case? And how SHOULD I have defined these functions to get the expected results? I'm assuming something is wrong with my lambda expressions...
I wish I could just comment, but alas, I don't have enough karma.
The other answers are all good ones, but I think the biggest confusion seems to be stemming from your use of x and xs.
If you rewrote it as
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = foldr (\y ys -> (f y):ys) [] xs
you would clearly see that x is not even mentioned on the right-hand side, so there's no way that it could be in the solution.
Cheers
For your first question, foldr already has a case for the empty list, so you need not and should not provide a case for it in your own map.
map' f = foldr (\x xs -> f x : xs) []
The same holds for filter'
filter' p = foldr (\x xs -> if p x then x : xs else xs) []
Nothing is wrong with your lambda expressions, but there is something wrong with your definitions of filter' and map'. In the cons case (x:xs) you eat the head (x) away and then pass the tail to foldr. The foldr function can never see the first element you already ate. :)
Alse note that:
filter' p = foldr (\x xs -> if p x then x : xs else xs) []
is equivalent (η-equivalent) to:
filter' p xs = foldr (\x xs -> if p x then x : xs else xs) [] xs
I would define map using foldr and function composition as follows:
map :: (a -> b) -> [a] -> [b]
map f = foldr ((:).f) []
And for the case of filter:
filter :: (a -> Bool) -> [a] -> [a]
filter p = foldr (\x xs -> if p x then x:xs else xs) []
Note that it is not necessary to pass the list itself when defining functions over lists using foldr or foldl.
The problem with your solution is that you drop the head of the list and then apply the map over the list and
this is why the head of the list is missing when the result is shown.
In your definitions, you are doing pattern matching for x:xs, which means, when your argument is [1,2,3,4], x is bound to 1 and xs is bound to the rest of the list: [2,3,4].
What you should not do is simply throw away x: part. Then your foldr will be working on whole list.
So your definitions should look as follows:
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f xs = foldr (\x xs -> (f x):xs) [] xs
and
filter' :: (a -> Bool) -> [a] -> [a]
filter' p [] = []
filter' p xs = foldr (\x xs -> if p x then x:xs else xs ) [] xs
I am new to Haskell (in fact I've found this page asking the same question) but this is my understanding of lists and foldr so far:
lists are elements that are linked to the next element with the cons (:) operator. they terminate with the empty list []. (think of it as a binary operator just like addition (+) 1+2+3+4 = 10, 1:2:3:4:[] = [1,2,3,4]
foldr function takes a function that takes two parameters. this will replace the cons operator, which will define how each item is linked to the next.
it also takes the terminal value for the operation, which can be tought as the initial value that will be assigned to the empty list. for cons it is empty list []. if you link an empty list to any list the result is the list itself. so for a sumfunction it is 0. for a multiply function it is 1, etc.
and it takes the list itself
So my solution is as follows:
filter' p = foldr (\x n -> if p x then x : n else n) []
the lambda expression is our link function, which will be used instead of the cons (:) operator. Empty list is our default value for an empty list. If predicate is satisfied we link to the next item using (:) as normal, else we simply don't link at all.
map' f = foldr (\x n -> f x : n) []
here we link f x to the next item instead of just x, which would simply duplicate the list.
Also, note that you don't need to use pattern matching, since we already tell foldr what to do in case of an empty list.
I know this question is really old but I just wanted to answer it anyway. I hope it is not against the rules.
A different way to think about it - foldr exists because the following recursive pattern is used often:
-- Example 1: Sum up numbers
summa :: Num a => [a] -> a
summa [] = 0
summa (x:xs) = x + suma xs
Taking the product of numbers or even reversing a list looks structurally very similar to the previous recursive function:
-- Example 2: Reverse numbers
reverso :: [a] -> [a]
reverso [] = []
reverso (x:xs) = x `op` reverso xs
where
op = (\curr acc -> acc ++ [curr])
The structure in the above examples only differs in the initial value (0 for summa and [] for reverso) along with the operator between the first value and the recursive call (+ for summa and (\q qs -> qs ++ [q]) for reverso). So the function structure for the above examples can be generally seen as
-- Generic function structure
foo :: (a -> [a] -> [a]) -> [a] -> [a] -> [a]
foo op init_val [] = init_val
foo op init_val (x:xs) = x `op` foo op init_val xs
To see that this "generic" foo works, we could now rewrite reverso by using foo and passing it the operator, initial value, and the list itself:
-- Test: reverso using foo
foo (\curr acc -> acc ++ [curr]) [] [1,2,3,4]
Let's give foo a more generic type signature so that it works for other problems as well:
foo :: (a -> b -> b) -> b -> [a] -> b
Now, getting back to your question - we could write filter like so:
-- Example 3: filter
filtero :: (a -> Bool) -> [a] -> [a]
filtero p [] = []
filtero p (x:xs) = x `filterLogic` (filtero p xs)
where
filterLogic = (\curr acc -> if (p curr) then curr:acc else acc)
This again has a very similar structure to summa and reverso. Hence, we should be able to use foo to rewrite it. Let's say we want to filter the even numbers from the list [1,2,3,4]. Then again we pass foo the operator (in this case filterLogic), initial value, and the list itself. filterLogic in this example takes a p function, called a predicate, which we'll have to define for the call:
let p = even in foo (\curr acc -> if (p curr) then curr:acc else acc) [] [1,2,3,4]
foo in Haskell is called foldr. So, we've rewritten filter using foldr.
let p = even in foldr (\curr acc -> if (p curr) then curr:acc else acc) [] [1,2,3,4]
So, filter can be written with foldr as we've seen:
-- Solution 1: filter using foldr
filtero' :: (a -> Bool) -> [a] -> [a]
filtero' p xs = foldr (\curr acc -> if (p curr) then curr:acc else acc) [] xs
As for map, we could also write it as
-- Example 4: map
mapo :: (a -> b) -> [a] -> [b]
mapo f [] = []
mapo f (x:xs) = x `op` (mapo f xs)
where
op = (\curr acc -> (f curr) : acc)
which therefore can be rewritten using foldr. For example, to multiply every number in a list by two:
let f = (* 2) in foldr (\curr acc -> (f curr) : acc) [] [1,2,3,4]
So, map can be written with foldr as we've seen:
-- Solution 2: map using foldr
mapo' :: (a -> b) -> [a] -> [b]
mapo' f xs = foldr (\curr acc -> (f curr) : acc) [] xs
Your solution almost works .)
The problem is that you've got two differend bindings for x in both your functions (Inside the patternmatching and inside your lambda expression), therefore you loose track of the first Element.
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = foldr (\x xs -> (f x):xs) [] (x:xs)
filter' :: (a -> Bool) -> [a] -> [a]
filter' p [] = []
filter' p (x:xs) = foldr (\x xs -> if p x then x:xs else xs ) [] (x:xs)
This should to the trick :). Also: you can write your functions pointfree style easily.
*Main> :{
*Main| map' :: (a -> b) -> [a] -> [b]
*Main| map' = \f -> \ys -> (foldr (\x -> \acc -> f x:acc) [] ys)
*Main| :}
*Main> map' (^2) [1..10]
[1,4,9,16,25,36,49,64,81,100]
*Main> :{
*Main| filter' :: (a -> Bool) -> [a] -> [a]
*Main| filter' = \p -> \ys -> (foldr (\x -> \acc -> if p x then x:acc else acc) [] ys)
*Main| :}
*Main> filter' (>10) [1..100]
In the above snippets acc refers to accumulator and x refers to the last element.
Everything is correct in your lambda expressions. The problem is you are missing the first element in the list. If you try,
map' f (x:xs) = foldr (\x xs -> f x:xs) [] (x:xs)
then you shouldn't miss the first element anymore. The same logic applies to filter.
filter' p (x:xs) = foldr(\ y xs -> if p y then y:xs else xs) [] (x:xs)

Resources