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
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.