user3928256
user3928256

Reputation: 1003

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?

Upvotes: 2

Views: 250

Answers (3)

Luis Casillas
Luis Casillas

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

Random Dev
Random Dev

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

Zeta
Zeta

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

Related Questions