There is a similar question I found here that asks almost the same thing, but not quite.
The question I have is how to compose a list of functions of type (a -> Bool) to be one function that is also (a -> Bool).
Ex.
compose :: [(a -> Bool)] -> (a -> Bool)
compose [] = **?**
compose (x:xs) = x **?** compose xs
The question that was similar to this was taking three functions and mixing them all like so:
newFunction x f g y = f x || g x || y x
But this is very limited because you have to supply a specific number of functions, and it does not return another function, it returns a Boolean. I essentially want a function that gives me the above function without functions as arguments.
I tried messing with Monoids to make this work but I ran into issues with wrapping the functions into a Monoid in the first place, let alone actually composing them together as newFunction does.
Is there a way to compose a list of functions of type (a -> Bool) to one function of the same type?
We can make use of any :: Foldable => (a -> Bool) -> f a -> Bool here:
compose :: Foldable f => f (a -> Bool) -> a -> Bool
compose = flip (any . flip ($))
or as #chepner suggests, with a (&):
import Data.Function((&))
compose :: Foldable f => f (a -> Bool) -> a -> Bool
compose = flip (any . (&))
or without the point-free styling (and probably simpler to understand):
compose :: Foldable f => f (a -> Bool) -> a -> Bool
compose l x = any ($ x) l
The above will work with any sort of Foldable, so a list [], Maybe, etc.
Look: compose xs in your definition is a function. So you can call it with an argument - like compose xs a, - and that will return a Bool.
You can use this to define the recursive case.
First of all, the recursive case must return a function - because that's what your type signature states. So it must look something like:
compose (x:xs) = \a -> ...
Now, the logic would go like this: first of all, call the first function in the list - like x a, - and if it returns true, then that's the result; otherwise, call the composition of the tail - like compose xs a. Let's write that down:
compose (x:xs) = \a -> x a || compose xs a
Next up, you need to decide what to do with the empty list. Obviously it can be either a function that always returns True or a function that always returns False, there can be no other options unless you can inspect the argument somehow, which you can't, because it's of generic type.
So, should it return True or False? Let's see: if it returns True, then any composition will always be True, that's how the || operator works. So we might as well just write compose _ = \_ -> True. Therefore, the only sane variant is for it to return False.
Summing up all of the above, here's your definition:
compose [] = \a -> False
compose (x:xs) = \a -> x a || compose xs a
And of course, you can use a shorter syntax instead of returning lambdas:
compose [] a = False
compose (x:xs) a = x a || compose xs a
To implement this using monoids you can use the Any (from Data.Monoid) boolean wrapper which implements the disjunction behaviour you want when combining values e.g.
(Any False) `mappend` (Any True)
=> Any {getAny = True}
Functions which return monoidal values are themselves monoids - mappending two such functions returns a function which evalulates the argument on both functions and mappends the results e.g.
f :: Int -> Any
f x = Any $ x > 10
g :: Int -> Any
g x = Any $ x < 3
comp :: Int -> Any
comp = f `mappend` g
comp 0
=> Any {getAny = True}
comp 4
=> Any {getAny = False}
comp 11
=> Any {getAny = True}
So if you lift each a -> Bool into a function a -> Any then these be composed with mappend.
mconcat reduces a list of monoidal values into a single value so applying this to a list of a -> Any function returns a function which applies the disjunction to each result. You then need to unwrap the Bool from the resulting Any value with getAny.
import Data.Monoid
compose :: [(a -> Bool)] -> (a -> Bool)
compose fs x = let anyfs = map (\f -> Any . f) fs
combined = mconcat anyfs
anyResult = combined x
in getAny anyResult
This can also be written as:
compose :: [(a -> Bool)] -> (a -> Bool)
compose = (getAny .) . mconcat . (map (Any .))
As danidiaz points out in the comments, you can also use foldMap. This also has a more general type:
compose :: Foldable t => t (a -> Bool) -> a -> Bool
compose = (getAny .) . foldMap (Any .)
A simpler example (I am no Haskeller), based on your requirements:
compose :: [(a -> Bool)] -> (a -> Bool)
compose [] = (\y -> False)
compose (x:xs) = (\y -> (x y) || ((compose xs) y))
I am just starting to learn Haskell and I have the assignment to use higher order functions to create a function with the following type definition
-- compr :: (a->b) -> (a -> Bool) -> [a] -> [b]
The function is not relevant, can be the simplest functions so my idea was like this:
identity x = x
booleans x | x == 1 = True
| x ==0 = False
| otherwise = False
compr identity booleans xs = filter booleans(map (identity) xs)
but this function has this type
compr :: (a->b) -> (b -> Bool) -> [a] -> [b]
I have tried everything but with no positive results. I hope you can help me.
You almost got it, but you need to apply the filter before the map. In that way, the filter applies to [a] instead of [b], and the predicate gets the right type.
> compr identity booleans xs = map identity (filter booleans xs)
> :t compr
compr :: (a -> b) -> (a -> Bool) -> [a] -> [b]
By the way, I find the names you use for your variables to be misleading. For instance, the identity variable in the definition of compr has nothing to do with the identity function you declared before.
I'd suggest you use more generic variable names instead, e.g.
> compr f p xs = map f (filter p xs)
where f stands for "function" and p for predicate.
There is already a standard library function in Haskell called id (id :: a -> a) to replace your identity function. So accordingly depending on how you will define your booleans function you might simplify your comp function as follows;
booleans x | x == 1 = True
| otherwise = False
compr :: (a -> Bool) -> [a] -> [a]
compr = filter booleans . map id
*Main> compr booleans [1,2,3,4]
[1]
I'm trying to write something like this in Haskell:
length . nub . intersect
but it doesn't work.
*Main Data.List> :t intersect
intersect :: Eq a => [a] -> [a] -> [a]
*Main Data.List> :t nub
nub :: Eq a => [a] -> [a]
*Main Data.List> :t length
length :: [a] -> Int
Based on the type, my understanding is that intersect returns a type of [a] and donates to nub , which takes exactly a type of [a] , then also returns a type of [a] to length , then finally the return should be an Int. What's wrong with it?
The problem here is that intersect takes 2 arguments (in a sense)
you can provide one of the arguments explicitly:
> let f a = length . nub . intersect a
> :t f
f :: Eq a => [a] -> [a] -> Int
or you can use a fun little operator like (.:) = (.) . (.):
> let (.:) = (.) . (.)
> :t length .: (nub .: intersect)
length .: (nub .: intersect) :: Eq a => [a] -> [a] -> Int
here is a version where you don't need the parens:
import Data.List
infixr 9 .:
(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.:) = (.).(.)
f :: Eq a => [a] -> [a] -> Int
f = length .: nub .: intersect
I guess this is based on the comments in your previous question, where #CarstenKönig mentions (.) . (.).
First of all, length . nub . intersect cannot work. Your types are:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
length :: [a] -> Int
nub :: Eq a => [a] -> [a]
intersect :: Eq a => [a] -> [a] -> [a] ~ [a] -> ([a] -> [a])
As you can see, intersect has the wrong type, in the context of (.), the type parameter b would be replaced by ([a] -> [a]), which isn't the type of nub's first argument.
I'd say this: write your code the "dumb" way at first, and then refactor it to use (.). After some practice the composition operator will then become like second nature.
So you'd first write:
yourFunction xs ys = length (nub (intersect xs ys))
What (.) lets you do is get rid (syntactically) of the last argument of the innermost function, all all the parens. In this case that argument is ys:
yourFunction xs = length . nub . intersect xs
Completely new to Haskell and learning through Learn Haskell the greater good.
I am looking at the map function
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
is it possible to add a predicate to this? for example, to only map to every other element in the list?
You can code your own version of map to apply f only to even (or odd) positions as follows. (Below indices start from 0)
mapEven :: (a->a) -> [a] -> [a]
mapEven f [] = []
mapEven f (x:xs) = f x : mapOdd f xs
mapOdd :: (a->a) -> [a] -> [a]
mapOdd f [] = []
mapOdd f (x:xs) = x : mapEven f xs
If instead you want to exploit the library functions, you can do something like
mapEven :: (a->a) -> [a] -> [a]
mapEven f = map (\(flag,x) -> if flag then f x else x) . zip (cycle [True,False])
or even
mapEven :: (a->a) -> [a] -> [a]
mapEven f = map (uncurry (\flag -> if flag then f else id)) . zip (cycle [True,False])
If you want to filter using an arbitrary predicate on the index, then:
mapPred :: (Int -> Bool) -> (a->a) -> [a] -> [a]
mapPred p f = map (\(i,x) -> if p i then f x else x) . zip [0..]
A more direct solution can be reached using zipWith (as #amalloy suggests).
mapEven :: (a->a) -> [a] -> [a]
mapEven f = zipWith (\flag x -> if flag then f x else x) (cycle [True,False])
This can be further refined as follows
mapEven :: (a->a) -> [a] -> [a]
mapEven f = zipWith ($) (cycle [f,id])
The "canonical" way to perform filtering based on positions is to zip the sequence with the naturals, so as to append an index to each element:
> zip [1, 1, 2, 3, 5, 8, 13] [0..]
[(1,0),(1,1),(2,2),(3,3),(5,4),(8,5),(13,6)]
This way you can filter the whole thing using the second part of the tuples, and then map a function which discards the indices:
indexedFilterMap p f xs = (map (\(x,_) -> f x)) . (filter (\(_,y) -> p y)) $ (zip xs [0..])
oddFibsPlusOne = indexedFilterMap odd (+1) [1, 1, 2, 3, 5, 8, 13]
To be specific to you question, one might simply put
mapEveryOther f = indexedFilterMap odd f
You can map with a function (a lambda is also possible):
plusIfOdd :: Int -> Int
plusIfOdd a
| odd a = a
| otherwise = a + 100
map plusIfOdd [1..5]
As a first step, write the function for what you want to do to the individual element of the list:
applytoOdd :: Integral a => (a -> a) -> a -> a
applytoOdd f x = if odd x
then (f x)
else x
So applytoOdd function will apply the function f to the element if the element is odd or else return the same element if it is even. Now you can apply map to that like this:
λ> let a = [1,2,3,4,5]
λ> map (applytoOdd (+ 100)) a
[101,2,103,4,105]
Or if you want to add 200 to it, then:
λ> map (applytoOdd (+ 200)) a
[201,2,203,4,205]
Looking on the comments, it seems you want to map based on the index position. You can modify your applytoOdd method appropriately for that:
applytoOdd :: Integral a => (b -> b) -> (a, b) -> b
applytoOdd f (x,y) = if odd x
then (f y)
else y
Here, the type variable a corresponds to the index element. If it's odd you are applying the function to the actual element of the list. And then in ghci:
λ> map (applytoOdd (+ 100)) (zip [1..5] [1..])
[101,2,103,4,105]
λ> map (applytoOdd (+ 200)) (zip [1..5] [1..])
[201,2,203,4,205]
Or use a list comprehension:
mapOdd f x = if odd x then f x else x
[ mapOdd (+100) x | x <- [1,2,3,4,5]]
I'm glad that you're taking the time to learn about Haskell. It's an amazing language. However it does require you to develop a certain mindset. So here's what I do when I face a problem in Haskell. Let's start with your problem statement:
Is it possible to add a predicate to the map function? For example, to only map to every other element in the list?
So you have two questions:
Is it possible to add a predicate to the map function?
How to map to every other element in the list?
So the way people think in Haskell is via type signatures. For example, when an engineer is designing a building she visualizes how the building should look for the top (top view), the front (front view) and the side (side view). Similarly when functional programmers write code they visualize their code in terms of type signatures.
Let's start with what we know (i.e. the type signature of the map function):
map :: (a -> b) -> [a] -> [b]
Now you want to add a predicate to the map function. A predicate is a function of the type a -> Bool. Hence a map function with a predicate will be of the type:
mapP :: (a -> Bool) -> (a -> b) -> [a] -> [b]
However, in your case, you also want to keep the unmapped values. For example mapP odd (+100) [1,2,3,4,5] should result in [101,2,103,4,105] and not [101,103,105]. Hence it follows that the type of the input list should match the type of the output list (i.e. a and b must be of the same type). Hence mapP should be of the type:
mapP :: (a -> Bool) -> (a -> a) -> [a] -> [a]
It's easy to implement a function like this:
map :: (a -> Bool) -> (a -> a) -> [a] -> [a]
mapP p f = map (\x -> if p x then f x else x)
Now to answer your second question (i.e. how to map to every other element in the list). You could use zip and unzip as follows:
snd . unzip . mapP (odd . fst) (fmap (+100)) $ zip [1..] [1,2,3,4,5]
Here's what's happening:
We first zip the index of each element with the element itself. Hence zip [1..] [1,2,3,4,5] results in [(1,1),(2,2),(3,3),(4,4),(5,5)] where the fst value of each pair is the index.
For every odd index element we apply the (+100) function to the element. Hence the resulting list is [(1,101),(2,2),(3,103),(4,4),(5,105)].
We unzip the list resulting in two separate lists ([1,2,3,4,5],[101,2,103,4,105]).
We discard the list of indices and keep the list of mapped results using snd.
We can make this function more general. The type signature of the resulting function would be:
mapI :: ((Int, a) -> Bool) -> (a -> a) -> [a] -> [a]
The definition of the mapI function is simple enough:
mapI :: ((Int, a) -> Bool) -> (a -> a) -> [a] -> [a]
mapI p f = snd . unzip . mapP p (fmap f) . zip [1..]
You can use it as follows:
mapI (odd . fst) (+100) [1,2,3,4,5]
Hope that helps.
Is it possible to add a predicate to this? for example, to only map to every other element in the list?
Yes, but functions should ideally do one relatively simple thing only. If you need to do something more complicated, ideally you should try doing it by composing two or more functions.
I'm not 100% sure I understand your question, so I'll show a few examples. First: if what you mean is that you only want to map in cases where a supplied predicate returns true of the input element, but otherwise just leave it alone, then you can do that by reusing the map function:
mapIfTrue :: (a -> Bool) -> (a -> a) -> [a] -> [a]
mapIfTrue pred f xs = map step xs
where step x | pred x = f x
| otherwise = x
If what you mean is that you want to discard list elements that don't satisfy the predicate, and apply the function to the remaining ones, then you can do that by combining map and filter:
filterMap :: (a -> Bool) -> (a -> b) -> [a] -> [b]
filterMap pred f xs = map f (filter pred xs)
Mapping the function over every other element of the list is different from these two, because it's not a predicate over the elements of the list; it's either a structural transformation of the list of a stateful traversal of it.
Also, I'm not clear whether you mean to discard or keep the elements you're not applying the function to, which would imply different answers. If you're discarding them, then you can do it by just discarding alternate list elements and then mapping the function over the remaining ones:
keepEven :: [a] -> [a]
keepEven xs = step True xs
where step _ [] = []
step True (x:xs) = x : step False xs
step False (_:xs) = step True xs
mapEven :: (a -> b) -> [a] -> [b]
mapEven f xs = map f (keepEven xs)
If you're keeping them, one way you could do it is by tagging each list element with its position, filtering the list to keep only the ones in even positions, discard the tags and then map the function:
-- Note: I'm calling the first element of a list index 0, and thus even.
mapEven :: (a -> a) -> [a] -> [a]
mapEven f xs = map aux (filter evenIndex (zip [0..] xs))
where evenIndex (i, _) = even i
aux (_, x) = f x
As another answer mentioned, zip :: [a] -> [b] -> [(a, b)] combines two lists pairwise by position.
But this is the general philosophy: to do a complex thing, use a combination of general-purpose generic functions. If you're familiar with Unix, it's similar to that.
Another simple way to write the last one. It's longer, but keep in mind that evens, odds and interleave all are generic and reusable:
evens, odds :: [a] -> [a]
evens = alternate True
odds = alternate False
alternate :: Bool -> [a] -> [a]
alternate _ [] = []
alternate True (x:xs) = x : alternate False xs
alternate False (_:xs) = alternate True xs
interleave :: [a] -> [a] -> [a]
interleave [] ys = ys
interleave (x:xs) ys = x : interleave ys xs
mapEven :: (a -> a) -> [a] -> [a]
mapEven f xs = interleave (map f (evens xs)) (odds xs)
You can't use a predicate because predicates operate on list values, not their indices.
I quite like this format for what you're trying to do, since it makes the case handling quite clear for the function:
newMap :: (t -> t) -> [t] -> [t]
newMap f [] = [] -- no items in list
newMap f [x] = [f x] -- one item in list
newMap f (x:y:xs) = (f x) : y : newMap f xs -- 2 or more items in list
For example, running:
newMap (\x -> x + 1) [1,2,3,4]
Yields:
[2,2,4,4]