Question

I've seen this type before without knowing what it means. Does it mean something and/or does it have a name?

Prelude> :m Data.Functor
Prelude Data.Functor> :t flip . (flip (<$>))
flip . (flip (<$>))
:: Functor ((->) b) => (b -> a) -> b -> (a -> c) -> c
Was it helpful?

Solution 2

To add to Matt Fenwick and josefg's more technical answers, the ((->) a can be read as the type constructor that forms values that depend on an a. One example: suppose you have teams whose membership varies over time. One possible way to represent this is like this:

-- | The type of a's that depend on a point in time, using t as the timeline type.
type Historical t a = t -> a

observe :: Historical t a -> t -> a
observe = ($)

-- | The membership of a team is a list of persons whose composition can change
-- from day to day.
membership :: Team -> Historical Day [Person]
membership = ...

((->) a) is a Functor, Applicative and Monad, which means that the type class operations are available, and they have very useful interpretations when used with Historical t.

First example: fmap applies a function to a time-dependent value. So for example,

-- The number of persons in a Team, depending on the Day:
membershipCount :: Team -> Historical Day Int
membershipCount = fmap length . membership

The Applicative <*> operation gives you simultaneity:

-- The joint membership of team1 and team2, depending on the Day:
(++) <$> membership team1 <*> membership team2 :: Historical Day [Person]

Though actually, since we have instance Monoid [a] and instance Monoid m => Monoid t -> m, the previous example can be written like this:

import Data.Monoid

membership team1 ++ membership team2

Monad gives you composition:

personToManager :: Person -> Historical Day Manager
personToManager = ...

managerToVP :: Manager -> Historical Day VP
managerToVP = ...

personToVP :: Person -> Historical Day VP
personToVP p = personToManager p >>= managerToVP

Note also that ((->) r is exactly the same as the Reader r monad. If you understand the code above you pretty much understand Reader.


EDIT: I should clarify that time-dependent values is just one use of the function/Reader monad. There are other uses; the classic example use case of the Reader monad is to thread configuration values through a computation. It's got rather more uses than just that, as the example above shows.

OTHER TIPS

Actually, ((->) a) is not a type but a partially applied type constructor.

Just like functions, type constructors can be partially applied in Haskell.

You can check the kind of something in GHCi:

ghci> :k (->)
(->) :: * -> * -> *

ghci> :k (->) Int
(->) Int :: * -> *

All values have types of kind *; type constructors have kinds like * -> *, * -> * -> *, etc.

In Haskell, (->) a is from a -> something. Remember that you can turn an operator to a prefixed function by using parans. ie (+) 1 1 == 2. So in this case the "operator" is the type constructor ->. It's used this way because a functor needs a type constructor with 1 variable, but -> has 2. So we partially apply it.

It may help you to realize that <$> for ((->) a) is just (.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top