So you can't just remove the e since it doesn't technically appear at the end of the definition. However, if you define the operator
(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.:) = (.) . (.)
Then you can write it as
numocc = map length .: (map . filter . (==))
The parentheses on map . filter . (==) are required since you can't mix . and .: due to fixity rules.
However, at this point you're just making this function harder to read and maintain. It would be better to break it down into smaller sections and introduce some intermediate names, along with adding the right type signature and giving the function a better name to start with:
numOccurrences :: Eq a => a -> [a] -> Int
numOccurrences valueToCount values = length (filter (== valueToCount) values)
numOccurrencesInSublists :: Eq a => a -> [[a]] -> [Int]
numOccurrencesInSublists valueToCount = map (numOccurrences valueToCount)
This is far more readable, doesn't rely on fancy operators, and expresses your intent more clearly. Since the case for counting in a single list is a separate function, you can now use it elsewhere too.
Remember, elegant code isn't about making it as short as possible, it's about making it as clear as possible. Descriptive names (not necessarily long ones), explicit arguments, and small, composable units are best.
Asked in February 2016Viewed 2,798 timesVoted 7Answered 1 times