简体   繁体   中英

Haskell Type Error From Function Application to Function Composition

This question is related to this Function Composition VS Function Application which answered by antal sz.

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.

That's just because function application xy has higher precedence than composition x . y x . y

 test :: [Char] -> Bool
 test xs = (not . null) xs
 -- #      ^          ^

 getMiddleInitials :: [String] -> [Char]
 getMiddleInitials middleNames = (map head . filter (\mn -> (not . null) mn)) middleNames
 -- #                            ^                          ^          ^    ^

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) 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 ( eg 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 ).

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM