Reputation: 1003
I'm trying to write something like this in Haskell:
length . nub . intersect
but it doesn't work.
*Main Data.List> :t intersect
intersect :: Eq a => [a] -> [a] -> [a]
*Main Data.List> :t nub
nub :: Eq a => [a] -> [a]
*Main Data.List> :t length
length :: [a] -> Int
Based on the type, my understanding is that intersect
returns a type of [a]
and donates to nub
, which takes exactly a type of [a]
, then also returns a type of [a]
to length
, then finally the return should be an Int
. What's wrong with it?
Upvotes: 2
Views: 250
Reputation: 30237
I'd say this: write your code the "dumb" way at first, and then refactor it to use (.)
. After some practice the composition operator will then become like second nature.
So you'd first write:
yourFunction xs ys = length (nub (intersect xs ys))
What (.)
lets you do is get rid (syntactically) of the last argument of the innermost function, all all the parens. In this case that argument is ys
:
yourFunction xs = length . nub . intersect xs
Upvotes: 2
Reputation: 52290
The problem here is that intersect
takes 2 arguments (in a sense)
you can provide one of the arguments explicitly:
> let f a = length . nub . intersect a
> :t f
f :: Eq a => [a] -> [a] -> Int
or you can use a fun little operator like (.:) = (.) . (.)
:
> let (.:) = (.) . (.)
> :t length .: (nub .: intersect)
length .: (nub .: intersect) :: Eq a => [a] -> [a] -> Int
here is a version where you don't need the parens:
import Data.List
infixr 9 .:
(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.:) = (.).(.)
f :: Eq a => [a] -> [a] -> Int
f = length .: nub .: intersect
Upvotes: 6
Reputation: 105905
I guess this is based on the comments in your previous question, where @CarstenKönig mentions (.) . (.)
.
First of all, length . nub . intersect
cannot work. Your types are:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
length :: [a] -> Int
nub :: Eq a => [a] -> [a]
intersect :: Eq a => [a] -> [a] -> [a] ~ [a] -> ([a] -> [a])
As you can see, intersect
has the wrong type, in the context of (.)
, the type parameter b
would be replaced by ([a] -> [a])
, which isn't the type of nub
's first argument.
Upvotes: 4