Types and higher-order function in Haskell - haskell

Could someone help me to understand this issue.
I have this simple function:
takeAsLong :: [a] -> (a -> Bool) -> [a]
takeAsLong [] _ = []
takeAsLong (x:xs) test | test x = x : takeAsLong xs test
| otherwise = []
But when I try to rewrite it using if-then-else I have an error.
takeAsLong :: [a] -> (a -> Bool) -> [a]
takeAsLong [] _ = []
takeAsLong (x:xs) test = if test x then x : takeAsLong [xs] test else []
The error is in the recursive call of "takeAsLong [xs] test" but I dont understand why it doesnt like it?
Error msg:
Couldn't match type ‘a’ with ‘[a]’
Expected: [a] -> Bool
Actual: a -> Bool
‘a’ is a rigid type variable bound by
the type signature for:
takeAsLong :: forall a. [a] -> (a -> Bool) -> [a]
So why does it expect function test to be [a] -> Bool and why version with guards doesnt have same issue?

xs is a list of items except the first item. If you use [xs] then you wrapt that list in a singleton list.
You thus should call takeAsLong xs test instead of takeAsLong [xs] test:
takeAsLong :: [a] -> (a -> Bool) -> [a]
takeAsLong [] _ = []
takeAsLong (x:xs) test = if test x then x : takeAsLong xs test else []
Using an if-then-else is not that common. Usually the predicate will also be the first parameter. So a more "Haskell-ish" version is likely:
takeAsLong :: (a -> Bool) -> [a] -> [a]
takeAsLong p = go
where go [] = []
go (x:xs)
| p x = x : go xs
| otherwise = []
This function already exists and is known as takeWhile :: (a -> Bool) -> [a] -> [a]

The main problem here is in the part takeAsLong [xs] when you do that you are giving to the function takeAsLong :: [a] -> (a -> Bool) -> [a] a list of lists, takeAsLong :: [[a]] -> (a -> Bool) -> [a] that type is the one would work, but you type is the other one.
There is how to do it in #willem answer:
takeAsLong :: [a] -> (a -> Bool) -> [a]
takeAsLong [] _ = []
takeAsLong (x:xs) test = if test x then x : takeAsLong xs test else []

Related

Understanding Haskell function in a lambda calculus way

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])

Debugging type Errors in Haskell

I'm trying to write a function, returning all permutations from a list in Haskell:
perms :: [a] -> [[a]]
perms [] = [[]]
perms xs = map (\y -> concat_each y (perms (list_without y xs))) xs
list_without :: (Eq a) => a -> [a] -> [a]
list_without x xs =
filter (\y -> not (y==x)) xs
concat_each :: a -> [[a]] -> [[a]]
concat_each x xs =
map (\y -> x:y) xs
What I think happens in line3:
y is a and x is [a], so
list_without y xs is [a].
perms (list_without ...) is thus [[a]]
so concat_each y (perms ...) gets a and [[a]], resulting in [[a]]
So the function for map is a -> [[a]] and everything should be okay.
But the compiler seems to see things differently:
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for perms :: [a] -> [[a]]
at C:\Users\Philipp\Desktop\permutations.hs:1:10
Expected type: [a]
Actual type: [[a]]
Relevant bindings include
y :: a (bound at permutations.hs:3:18)
xs :: [a] (bound at permutations.hs:3:7)
perms :: [a] -> [[a]]
(bound at permutations.hs:2:1)
In the expression: concat_each y (perms (list_without y xs))
In the first argument of `map', namely
`(\ y -> concat_each y (perms (list_without y xs)))'
How would I debug this error message properly? I don't really know where to start checking my types.
map :: (x -> y) -> [x] -> [y]
The first argument you gave to map has type a -> [[a]], i.e., x = a and y = [[a]] so
:: [x] -> [ y ]
map (\y -> ...) :: [a] -> [[[a]]]
-- ^ ^^^^^
-- x = a, y = [[a]]
In this case, the result of that map (\y -> ...) xs is a list where each element corresponds to the permutations starting with a fixed element y in xs. In the end, you don't care which element a permutation starts with; you can forget that separation using concat:
perms = concat (map (\y -> ...) xs)
-- or
perms = concatMap (\y -> ...) xs
-- or
perms = xs >>= \y -> ...

Partition using recursion

Trying to learn myself some haskell, I know about the function
partition :: (a -> Bool) -> [a] -> ([a], [a])
would I be able to this using recursion rather than using the function. eg id have my own defined function
partition':: (a -> Bool) -> [a] -> ([a], [a])
which would use recursion
Here's one recursive definition:
partition':: (a -> Bool) -> [a] -> ([a], [a])
partition' _ [] = ([],[])
partition' f (x:xs) | f x = (x:matched,notMatched)
| otherwise = (matched,x:notMatched)
where (matched,notMatched) = partition' f xs

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]

Haskell, type matching problems

I cannot understand why the function:
repli :: [a] -> Int -> [a]
repli xs n = concatMap (replicate n) xs
cannot be rewritten as:
repli :: [a] -> Int -> [a]
repli [] _ = []
repli (x:xs) n = (take n $ repeat x) : repli xs n
or
repli :: [a] -> Int -> [a]
repli [] _ = []
repli (x:xs) n = (replicate n x) : repli xs n
Ghci complains:
Couldn't match expected type ‘a’ with actual type ‘[a]’
‘a’ is a rigid type variable bound by
the type signature for repli :: [a] -> Int -> [a]
at 99questions.hs:41:10
Relevant bindings include
xs :: [a] (bound at 99questions.hs:43:10)
x :: a (bound at 99questions.hs:43:8)
repli :: [a] -> Int -> [a] (bound at 99questions.hs:42:1)
In the first argument of ‘(:)’, namely ‘(replicate n x)’
In the expression: (replicate n x) : repli xs n
I don't understand why, since doing all the type computations it turns out ok. repeat x is [a] and so take n is [a]. Therefore it shouldn't complain.
The signature of (:) is a -> [a] -> [a]. Therefore, you cannot have lists on both sides of the operator. That's the cause of your error.
You could instead use (++), which has the signature [a] -> [a] -> [a].

Resources