I have managed to implement a mock filter functions (after lots of attempts)
filter' :: (Num a, Eq a) => (a -> Bool) -> [a] -> [a]
filter' a [] = []
filter' a (x:xs) = if a x
then x : filter' a xs
else filter' a xs
What I don't clearly understand is the type declaration
filter' :: (Num a, Eq a) => (a -> Bool) -> [a] -> [a]
-- filter' (<10) [1,2,3]
-- output = []
We pass in (<10) [1,2,3]
. However in the type declaration (a -> Bool)
we pass in a which comes from the list recursively and the output is either true or false. However what about the expressing the test (<10)?
Why don't we add another Bool?
The type of your filter'
function is only so constrained because you've declared that it is. If you don't declare the type, the compiler will infer a more tolerant type: (a -> Bool) -> [a] -> [a]
. This is the same type as the built-in filter
function:
Prelude> :type filter
filter :: (a -> Bool) -> [a] -> [a]
The expression (< 10)
is a so-called section . It's a partially applied function.
The operator <
is itself a function:
Prelude> :type (<)
(<) :: Ord a => a -> a -> Bool
You can read this as: <
is a function that takes two arguments, both of the generic type a
. The type a
must belong to the typeclass Ord
. When you call <
with such two values, a Bool
value is returned.
Since Haskell functions are curried , you can call a function with only some of the arguments. The return value is a new function that 'waits for the remaining arguments':
Prelude> :type (< 10)
(< 10) :: (Num a, Ord a) => a -> Bool
This type is a little more constrained, because the literal 10
is inferred to belong to the Num
typeclass. Since <
is in use, the original constraint for that ( Ord
) is still in effect as well.
The expression [1,2,3]
is is by the compiler inferred as:
Prelude> :type [1,2,3]
[1,2,3] :: Num t => [t]
The values all belong to the Num
typeclass. When you use all of these types together, you get the union of all the inferred types:
Prelude> :type filter (< 10) [1,2,3]
filter (< 10) [1,2,3] :: (Num a, Ord a) => [a]
The Num
typeclass is inferred because of the use of literals, and the Ord
typeclass is inferred because of the use of the <
operator.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.