Haskell: Using map in function composition - haskell

I am relatively new to Haskell so apologies if my question sounds stupid. I have been trying to understand how function composition works and I have come across a problem that I was wondering someone could help me with. I am using map in a function composition in the following two scenarios:
map (*2) . filter even [1,2,3,4]
map (*2) . zipWith max [1,2] [4,5]
Although both the filter and zipWith functions return a list, only the first composition works while the second composition throws the below error:
"Couldn't match expected type '[Int] -> [Int]' with actual type '[c0]'
Any suggestions would be greatly appreciated.

Recall the type of (.).
(.) :: (b -> c) -> (a -> b) -> a -> c
It takes three arguments: two functions and an initial value, and returns the result of the two functions composed.
Now, application of a function to its arguments binds tighter than the (.) operator.
So your expression:
map (*2) . filter even [1,2,3,4]
is parsed as:
(.) (map (*2)) (filter even [1,2,3,4])
now, the first argument, map (*2) is ok. It has type (b -> c), where b and c is Num a => [a]. However, the second argument is a single list:
Prelude> :t filter even [1,2,3,4]
filter even [1,2,3,4] :: Integral a => [a]
and so the type checker will complain that you're passing a [a] as an argument when the (.) function needs a function.
And that's what we see:
Couldn't match expected type `a0 -> [b0]' with actual type `[a1]'
In the return type of a call of `filter'
In the second argument of `(.)', namely `filter even [1, 2, 3, 4]'
In the expression: map (* 2) . filter even [1, 2, 3, 4]
So... parenthesization!
Either use the $ operator to add a parenthesis:
map (*2) . filter even $ [1,2,3,4]
or use explicit parens, removing the composition of two functions
map (*2) (filter even [1,2,3,4])
or even:
(map (*2) . filter even) [1,2,3,4]

The following forms are valid:
map (* 2) $ filter even [1, 2, 3, 4]
(map (* 2) . filter even) [1, 2, 3, 4]
map (* 2) $ zipWith max [1, 2] [4, 5]
(\xs -> map (* 2) . zipWith max xs) [1, 2] [4, 5]
but not the following:
map (* 2) . filter even [1, 2, 3, 4]
map (* 2) . zipWith max [1, 2] [4, 5]
(map (* 2) . zipWith max) [1, 2] [4, 5]
Why is that so? Well, take for example
map (* 2) . zipWith max [1, 2] [4, 5]
it is the same as
(map (* 2)) . (((zipWith max) [1, 2]) [4, 5])
(map (* 2)) has type [Int] -> [Int] (assuming defaulting for Int), (((zipWith max) [1, 2]) [4, 5]) has type [Int] and (.) has type (b -> c) -> (a -> b) -> a -> c or ([Int] -> [Int]) -> ([Int] -> [Int]) -> [Int] -> [Int] in this non-polymorphic case, so this is ill-typed. On the other hand ($) has type (a -> b) -> a -> b, or ([Int] -> [Int]) -> [Int] -> [Int] in this non-polymorphic case, so this:
(map (* 2)) $ (((zipWith max) [1, 2]) [4, 5])
is well-typed.

The result of zipWith max [1,2] [4,5] is a list, not a function. The (.) operator requires a function as its right operand. Hence the error on your second line. Probably what you want is
map (*2) (zipWith max [1,2] [4,5])
Your first example does not compile on WinHugs (Hugs mode); it has the same error. The following will work
(map (*2) . filter even) [1,2,3,4]
as it composes two functions and applies the resulting function to an argument.

Due to the low precedence of (.), Haskell parses
map (*2) . filter even [1,2,3,4]
as
map (*2) . (filter even [1,2,3,4])
i.e. compose map (*2) (a function) with the result of filter even [1,2,3,4] (a list), which makes no sense, and is a type error.
You can fix this using #Theodore's suggestions, or by using ($):
map (*2) . filter even $ [1,2,3,4]

If you check the type of map it is: (a -> b) -> [a] -> [b]
So, it takes a function of a into b and then a list of a and returns a list of b. Right?
Now, you already provide a function of a into b by passing the parameter (*2). So, your partially applied map function end up being: [Integer] -> [Integer] meaning that you will receive a list of integers and return a list of integers.
Up to this point, you could compose (.) a function that has the same signature. If you check what is the type of filter even you would see that it is: [Integer] -> [Integer], as such a valid candidate for composition here.
This composition then, does not alter the final signature of the function, if you check the type of: map (*2) . filter even it is [Integer] -> [Integer]
This would not be the case of the map (*2) . zipWith max [1,2] [4,5] because the zipWith max does not have the same signature as the one expected by map (*2).

Related

Haskell map list of indices to !! operator

When checking the type of map (!!) [1,2] in the ghci parser I get back: Num [a] => [Int -> a]. This has to do with the fact that the first argument of (!!) should be a list. However, I want to input a list of indices into the operator to get this type [a] -> [a].
EDIT
After the suggestion of #dfeuer to wrap it in another function I figured it would also be possible by using flip then. Checking the type of (map (flip (!!)) [1,2]) give the type [[c] -> c] which is what I am looking for.
If you have a list of indices and you want a function that selects those indices from an input list, then you want the map to iterate over the indices, not the input as you’re currently doing:
getIndices :: [Int] -> [a] -> [a]
getIndices indices input = map (input !!) indices
> getIndices [1, 2] "beans"
"ea"
If you want to write this in a more compact fashion using an inline list of indices, you can reduce away the input parameter like this:
\ input -> map (input !!) [1, 2]
\ input -> [1, 2] <&> (input !!) -- Data.Functor.(<&>) = flip (<$>)
\ input -> [1, 2] <&> (!!) input
\ input -> (([1, 2] <&>) . (!!)) input
([1, 2] <&>) . (!!)
In other words, flip map [1, 2] . (!!). But I think there isn’t anything to be gained from pointfree style in this case.
With a helper function (this name from lens):
flap, (??) :: Functor f => f (a -> b) -> a -> f b
flap f x = ($ x) <$> f
(??) = flap
infixl 1 ??
index :: Int -> [c] -> c
index = flip (!!)
This can be written:
> oneTwo = flap (index <$> [1, 2])
> oneTwo "beans"
"ea"
> index <$> [1, 2] ?? "bears"
"ea"
Or there’s always the boring but readable option of a list comprehension or do notation:
oneTwo xs = [xs !! i | i <- [1, 2]]
oneTwo xs = do { i <- [1, 2]; pure (xs !! i) }
I'm guessing you want
pickAndChoose :: [Int] -> [a] -> [a]
pickAndChoose indices values
= map (values !!) indices
Since !! takes time linear in the position of the element it retrieves, this will be quite inefficient if many indices are used, especially if they are relatively large. You may wish to consider using something like Data.Sequence instead of lists.

Stack overflow when folding infinite lists?

Consider the following function:
(<.>) :: [[a]] -> [[a]] -> [[a]]
xs <.> ys = zipWith (++) xs ys
This essentially takes two two-dimensional arrays of as and concatanates them, left to right, e.x.:
[[1,2],[3,4]] <.> [[1,2],[3,4]] == [[1,2,1,2],[3,4,3,4]]
I would like to be able to write something like the following:
x = foldr1 (<.>) $ repeat [[1,2],[3,4]]
Which should make sense due to Haskell's lazy evaluation, i.e. we should obtain:
x !! 0 == [1,2,1,2,1,2,1,2...]
x !! 1 == [3,4,3,4,3,4,3,4...]
However, when I try to run this example with GHCi, either using foldr1 or foldl1, I either get a non-terminating computation, or a stack overflow.
So my question is:
What's going on here?
Is it possible to do what I'm trying to accomplish here with some function other than foldr1 or foldl1? (I'm happy if I need to modify the implementation of <.>, as long as it computes the same function)
Also, note: I'm aware that for this example, map repeat [[1,2],[3,4]] produces the desired output, but I am looking for a solution that works for arbitrary infinite lists, not just those of the form repeat xs.
I'll expand on what's been said in the comments here. I'm going to borrow (a simplified version of) the GHC version of zipWith, which should suffice for the sake of this discussion.
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f [] _ = []
zipWith f _ [] = []
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
Now, here's what your computation ends up looking like, in it's glorious infinite form.
[[1, 2], [3, 4]] <.> ([[1, 2], [3, 4]] <.> ([[1, 2], [3, 4]] ... ) ... )
Okay, so the top-level is a <.>. Fine. Let's take a closer look at that.
zipWith (++) [[1, 2], [3, 4]] ([[1, 2], [3, 4]] <.> ([[1, 2], [3, 4]] ... ) ... )
Still no problems yet. Now we look at the patterns for zipWith. The first pattern only matches if the left-hand-side is empty. Welp, that's definitely not true, so let's move on. The second only matches if the right-hand-side is empty. So let's see if the right-hand-side is empty. The right-hand-side looks like
[[1, 2], [3, 4]] <.> ([[1, 2], [3, 4]] <.> ([[1, 2], [3, 4]] ... ) ... )
Which is what we started with. So to compute the result, we need access to the result. Hence, stack overflow.
Now, we've established that our problem is with zipWith. So let's play with it. First, we know we're going to be applying this to infinite lists for our contrived example, so we don't need that pesky empty list case. Get rid of it.
-- (I'm also changing the name so we don't conflict with the Prelude version)
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
(<.>) :: [[a]] -> [[a]] -> [[a]]
xs <.> ys = zipWith' (++) xs ys
But that fixes nothing. We still have to evaluate to weak head normal form (read: figure out of the list is empty) to match that pattern.
If only there was a way to do a pattern match without having to get to WHNF... enter lazy patterns. Let's rewrite our function this way.
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f ~(x:xs) ~(y:ys) = f x y : zipWith' f xs ys
Now our function will definitely break if given a finite list. But this allows us to "pretend" pattern match on the lists without actually doing any work. It's equivalent to the more verbose
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f xs ys = f (head xs) (head ys) : zipWith' f (tail xs) (tail ys)
And now we can test your function properly.
*Main> let x = foldr1 (<.>) $ repeat [[1, 2], [3, 4]]
*Main> x !! 0
[1,2,1,2,1,2,1,2,1,...]
*Main> x !! 1
[3,4,3,4,3,4,3,4,3,...]
The obvious downside of this is that it will definitely fail on finite lists, so you have to have a different function for those.
*Main> [[1, 2], [3, 4]] <.> [[1, 2], [3, 4]]
[[1,2,1,2],[3,4,3,4],*** Exception: Prelude.head: empty list
zipWith is not -- in fact, it can't possibly be -- as lazy as you'd like. Consider this variation on your example:
GHCi> foldr1 (zipWith (++)) [ [[1,2],[3,4]], [] ]
[]
Any empty list of lists in the input will lead to an empty list of lists result. That being so, there is no way to know any of the elements of the result until the whole input has been consumed. Therefore, your function won't terminate on infinite lists.
Silvio Mayolo's answer goes through some potential workarounds for this issue. My suggestion is using non-empty-lists of lists, instead of plain lists of lists:
GHCi> import qualified Data.List.NonEmpty as N
GHCi> import Data.List.NonEmpty (NonEmpty(..))
GHCi> take 10 . N.head $ foldr1 (N.zipWith (++)) $ repeat ([1,2] :| [[3,4]])
[1,2,1,2,1,2,1,2,1,2]
N.zipWith doesn't have to deal with an empty list case, so it can be lazier.

Haskell Curried Map

So I understand you can:
> f = map (+1)
> f [1,2,3]
[2,3,4]
However, what if you do:
> g = map (+) [1,2,3]
> :t g
g :: Num a => [a -> a]
I am not sure how to use g. What are its input & output?
One could, for example, apply each element of the list to a specific value:
> map (\f -> f 3) g
[4,5,6]
Or you could apply each function in the list to values in the corresponding position of another list:
> zipWith (\f x -> f x) g [30,300,3000]
[31,302,3003]
Or you could pattern match on the list, or use it in a list comprehension, or index it with (!!), or, or, or... there are endless possibilities.
(+) :: Num a => a -> a -> a; it takes an number and returns a function that increases its argument.
map (+) [1, 2, 3], then, is equivalent to [(+ 1), (+ 2), (+ 3)]. One way to use such a list of functions is with the Applicative instance of [], which allows you to apply each function in a list to each value in another list. For example:
[(+ 1), (+ 2), (+ 3)] <*> [5] == [6, 7, 8]

make function with 'if' point-free

I have a task in Haskell (no, it's not my homework, I'm learning for exam).
The task is:
Write point-free function numocc which counts occurrences of element in given lists. For example: numocc 1 [[1, 2], [2, 3, 2, 1, 1], [3]] = [1, 2, 0]
This is my code:
addif :: Eq a => a -> Int -> a -> Int
addif x acc y = if x == y then acc+1 else acc
count :: Eq a => a -> [a] -> Int
count = flip foldl 0 . addif
numocc :: Eq a => a -> [[a]] -> [Int]
numocc = map . count
numocc and count are 'point-free', but they are using function addif which isn't.
I have no idea how can I do the function addif point-free. Is there any way to do if statement point-free? Maybe there is a trick which use no if?
I would use the fact that you can easily convert a Bool to an Int using fromEnum:
addif x acc y = acc + fromEnum (x == y)
Now you can start applying the usual tricks to make it point-free
-- Go prefix and use $
addif x acc y = (+) acc $ fromEnum $ (==) x y
-- Swap $ for . when dropping the last argument
addif x acc = (+) acc . fromEnum . (==) x
And so on. I won't take away all the fun of making it point free, especially when there's tools to do it for you.
Alternatively, you could write a function like
count x = sum . map (fromEnum . (==) x)
Which is almost point free, and there are tricks that get you closer, although they get pretty nasty quickly:
count = fmap fmap fmap sum map . fmap fmap fmap fromEnum (==)
Here I think it actually looks nicer to use fmap instead of (.), although you could replace every fmap with (.) and it would be the exact same code. Essentially, the (fmap fmap fmap) composes a single argument and a two argument function together, if you instead give it the name .: you could write this as
count = (sum .: map) . (fromEnum .: (==))
Broken down:
> :t fmap fmap fmap sum map
Num a => (a -> b) -> [a] -> b
So it takes a function from b to a numeric a, a list of bs, and returns an a, not too bad.
> :t fmap fmap fmap fromEnum (==)
Eq a => a -> a -> Int
And this type can be written as Eq a => a -> (a -> Int), which is an important thing to note. That makes this function's return type match the input to fmap fmap fmap sum map with b ~ Int, so we can compose them to get a function of type Eq a => a -> [a] -> Int.
why not
numocc x
= map (length . filter (== x))
= map ((length .) (filter (== x)) )
= map (((length .) . filter) (== x))
= map (((length .) . filter) ((==) x))
= map (((length .) . filter . (==)) x)
= (map . ((length .) . filter . (==))) x
= (map . (length .) . filter . (==)) x
and then the trivial eta-contraction.
One trick would be to import one of the many if functions, e.g. Data.Bool.bool 1 0 (also found in Data.Bool.Extras).
A more arcane trick would be to use Foreign.Marshal.Utils.fromBool, which does exactly what you need here. Or the same thing, less arcane: fromEnum (thanks #bheklilr).
But I think the simplest trick would be to simply avoid counting yourself, and just apply the standard length function after filtering for the number.
Using the Enum instance for Bool, it is possible to build a pointfree replacement for if that can be used in more general cases:
chk :: Bool -> (a,a) -> a
chk = ([snd,fst]!!) . fromEnum
Using chk we can define a different version of addIf:
addIf' :: Eq a => a -> a -> Int -> Int
addIf' = curry (flip chk ((+1),id) . uncurry (==))
Now we can simply replace chk in addIf':
addIf :: Eq a => a -> a -> Int -> Int
addIf = curry (flip (([snd,fst]!!) . fromEnum) ((+1),id) . uncurry (==))
I think you’re looking for Data.Bool’s bool, which exists since 4.7.0.0 (2014–04–08).
incif :: (Eq a, Enum counter) => a -> a -> counter -> counter
incif = ((bool id succ) .) . (==)
The additional . allows == to take two parameters, before passing the expression to bool.
Since the order of parameters is different, you need to use incif like this:
(flip . incif)
(Integrating that into incif is left as an exercise to the reader. [Translation: It’s not trivial, and I don’t yet know how. ;])
Remember that in Haskell list comprehensions, if conditionals can be used in the result clause or at the end. But, most importantly, guards without if can be used to filter results. I am using pairs from zip. The second of the pair is the list number. It stays constant while the elements of the list are being compared to the constant (k).
Your result [1,2,0] does not include list numbers 1, 2 or 3 because it is obvious from the positions of the sums in the result list. The result here does not add the occurrences in each list but list them for each list.
nocc k ls = [ z | (y,z) <- zip ls [1..length ls], x <- y, k == x]
nocc 1 [[1, 2], [2, 3, 2, 1, 1], [3]]
[1,2,2] -- read as [1,2,0] or 1 in list 1, 2 in list 2 and 0 in list 3

Nested loop equivalent

I want to do a list of concatenations in Haskell.
I have [1,2,3] and [4,5,6]
and i want to produce [14,15,16,24,25,26,34,35,36].
I know I can use zipWith or sth, but how to do equivalent of:
foreach in first_array
foreach in second_array
I guess I have to use map and half curried functions, but can't really make it alone :S
You could use list comprehension to do it:
[x * 10 + y | x <- [1..3], y <- [4..6]]
In fact this is a direct translation of a nested loop, since the first one is the outer / slower index, and the second one is the faster / inner index.
You can exploit the fact that lists are monads and use the do notation:
do
a <- [1, 2, 3]
b <- [4, 5, 6]
return $ a * 10 + b
You can also exploit the fact that lists are applicative functors (assuming you have Control.Applicative imported):
(+) <$> (*10) <$> [1,2,3] <*> [4,5,6]
Both result in the following:
[14,15,16,24,25,26,34,35,36]
If you really like seeing for in your code you can also do something like this:
for :: [a] -> (a -> b) -> [b]
for = flip map
nested :: [Integer]
nested = concat nested_list
where nested_list =
for [1, 2, 3] (\i ->
for [4, 5, 6] (\j ->
i * 10 + j
)
)
You could also look into for and Identity for a more idiomatic approach.
Nested loops correspond to nested uses of map or similar functions. First approximation:
notThereYet :: [[Integer]]
notThereYet = map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]
That gives you nested lists, which you can eliminate in two ways. One is to use the concat :: [[a]] -> [a] function:
solution1 :: [Integer]
solution1 = concat (map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3])
Another is to use this built-in function:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f xs = concat (map f xs)
Using that:
solution2 :: [Integer]
solution2 = concatMap (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]
Other people have mentioned list comprehensions and the list monad, but those really bottom down to nested uses of concatMap.
Because do notation and the list comprehension have been said already. The only other option I know is via the liftM2 combinator from Control.Monad. Which is the exact same thing as the previous two.
liftM2 (\a b -> a * 10 + b) [1..3] [4..6]
The general solution of the concatenation of two lists of integers is this:
concatInt [] xs = xs
concatInt xs [] = xs
concatInt xs ys = [join x y | x <- xs , y <- ys ]
where
join x y = firstPart + secondPart
where
firstPart = x * 10 ^ lengthSecondPart
lengthSecondPart = 1 + (truncate $ logBase 10 (fromIntegral y))
secondPart = y
Example: concatInt [1,2,3] [4,5,6] == [14,15,16,24,25,26,34,35,36]
More complex example:
concatInt [0,2,10,1,100,200] [24,2,999,44,3] == [24,2,999,44,3,224,22,2999,244,23,1024,102,10999,1044,103,124,12,1999,144,13,10024,1002,100999,10044,1003,20024,2002,200999,20044,2003]

Resources