zoran119
zoran119

Reputation: 11307

Type error when using length inside filter

Given a list of lists, I'd like to find the maximum number of times a particular element occurs in one of the sub-lists.

So given [[1,4],[4,3],[1,4,4,3]] I expect output to be 2 because the number 4 occurs twice in one of the sub-lists (and no more than twice).

My approach was to eliminate all the numbers which are not 4 from the sublists, and then get the maximum length of all the sub-lists. The first step was OK:

map (filter (==4)) [[1,4],[4,3],[1,4,4,3]]

But adding length gives me an error:

map (length $ filter (==4)) [[1,4],[4,3],[1,4,4,3]]
Couldn't match expected type ‘[Integer] -> b’
            with actual type ‘Int’
Relevant bindings include it :: [b] (bound at <interactive>:11:1)
In the first argument of ‘map’, namely ‘(length $ filter (== 4))’
In the expression:
  map (length $ filter (== 4)) [[1, 4], [4, 3], [1, 4, 4, ....]]
In an equation for ‘it’:
    it = map (length $ filter (== 4)) [[1, 4], [4, 3], [1, 4, ....]]

Why doesn't this work? - Haskell noob if you did't notice :)

Upvotes: 0

Views: 87

Answers (1)

Clinton
Clinton

Reputation: 23135

You just need to compose length and filter (==4) with ., not $, because both length and filter (==4) are functions, not a function and a value, which you use $ for.

So you have:

map (length . filter (==4)) [[1,4],[4,3],[1,4,4,3]]

Alternatively, this would work also:

map (\x -> length $ filter (==4) x) [[1,4],[4,3],[1,4,4,3]]

but notice in this case you're applying filter (==4) x to length and filter (==4) x is a value itself, not a function, so $ is the correct composition operator.

But I'd argue the former is better Haskell style.

Upvotes: 7

Related Questions