Search code examples
haskellpointfreefunction-compositioncombinatorsdot-operator

How to use (.) in Haskell


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?


Solution

  • 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