问题
This question is related to this Function Composition VS Function Application which answered by antal s-z.
How you can get this ?
map has type (a -> b) -> [a] -> [b]
head has type [a] -> a
map head has type [[a]] -> [a]
Why the following code has type error for function composition ?
test :: [Char] -> Bool
test xs = not . null xs
getMiddleInitials :: [String] -> [Char]
getMiddleInitials middleNames = map head . filter (\mn -> not . null mn) middleNames
but this does not have type error
getFirstElements :: [[a]] -> [a]
getFirstElements = map head . filter (not . null)
Is it a must to write a point free function in order to utilize the function composition ? I still not very understand the usage of function composition.
Please help. Thanks.
回答1:
Your error here is actually really simple. If you remember the last part of my answer to your last question, the .
operator has higher precedence than anything except for function application. Thus, consider your example of
test :: [Char] -> Bool
test xs = not . null xs
This is parsed as test xs = not . (null xs)
. Of course, null xs
has type Bool
, and you can't compose a boolean, and so you get a type error. Thus, you could make your examples work like so:
test :: [Char] -> Bool
test xs = (not . null) xs
getMiddleInitials :: [String] -> [Char]
getMiddleInitials middleNames =
(map head . filter (\mn -> (not . null) mn)) middleNames
Of course, writing it this way is unusual, but it would work fine.
And no, there are other uses of function composition besides point-free style. One example is to use function composition for some things (e.g. the argument to map
or filter
), but specify the rest. For instance, take this contrived example:
rejectMapping :: (a -> Bool) -> (a -> b) -> [a] -> [b]
rejectMapping p f = map f . filter (not . p)
This is partly point-free (not . p
, for instance, and we left off the final argument), but partly point-full (the existence of p
and f
).
回答2:
That's just because function application x y
has higher precedence than composition x . y
test :: [Char] -> Bool
test xs = (not . null) xs
-- # ^ ^
getMiddleInitials :: [String] -> [Char]
getMiddleInitials middleNames = (map head . filter (\mn -> (not . null) mn)) middleNames
-- # ^ ^ ^ ^
来源:https://stackoverflow.com/questions/3123457/haskell-type-error-from-function-application-to-function-composition