I often read that
It seem that identity monad is useless. It's not... but that's another topic.
So can anyone tell my how is it useful?
I often read that
It seem that identity monad is useless. It's not... but that's another topic.
So can anyone tell my how is it useful?
Identity
is to monads, functors and applicative functors as 0 is to numbers. On its own it seems useless, but it's often needed in places where one expects a monad or an (applicative) functor that actually doesn't do anything.
As already mentioned, Identity
allows us to define just monad transformers and then define their corresponding monads just as SomeT Identity
.
But that's not all. It's often convenient to also define other concepts in terms of monads, which usually adds a lot of flexibility. For example Conduit i m o
(also see this tutorial) defines an element in a pipeline that can request data of type i
, can produce data of type o
, and uses monad m
for internal processing. Then such a pipeline can be run in the given monad using
($$) :: Monad m => Source m a -> Sink a m b -> m b
(where Source
is an alias for Conduit
with no input and Sink
for Conduit
with no output). And when no effectful computations are needed in the pipeline, just pure code, we just specialize m
to Identity
and run such a pipeline as
runIdentity (source $$ sink)
Identity
is also the "empty" functor and applicative functor: Identity
composed with another functor or applicative functor is isomorphic to the original. For example, Lens'
is defined as a function polymorphic in a Functor
:
Functor f => (a -> f a) -> s -> f s
roughly speaking, such a lens allows to read or manipulate something of type a
inside s
, for example a field inside a record (for an introduction to lenses see this post). If we specialize f
to Identity
, we get
(a -> Identity a) -> s -> Identity s
which is isomorphic to
(a -> a) -> s -> s
so given an updating function on a
, return an updating function on s
. (For completeness: If we specialize f
to Const a
, we get (a -> Const b a) -> s -> Const b s
, which is isomorphic to (a -> b) -> (s -> b)
, that is, given a reader on a
, return a reader on s
.)
Sometimes I work with records whose fields are optional in some contexts (like when parsing the record from JSON) but mandatory in others.
I solve that by parametrizing the record with a functor, and using Maybe
or Identity
in each case.
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE StandaloneDeriving #-}
data Query f = Query
{
_viewName :: String
, _target :: f Server -- Server is some type, it doesn't matter which
}
deriving (Generic)
The server field is optional when parsing JSON:
instance FromJSON (Query Maybe)
But then I have a function like
withDefaultServer :: Server -> Query Maybe -> Query Identity
withDefaultServer = undefined
that returns a record in which the _target
field is mandatory.
(This answer doesn't use anything monadic about Identity
, though.)
One use of it is as a base monad for monad transformer stacks: instead of having to provide two types Some :: * ->*
and SomeT :: (* -> *) -> * -> *
, it is enough to provide just a latter by setting type Some = SomeT Identity
.
Another, somewhat similar use case (but completely detached from the whole monad business) is when you need to refer to tuples: we can say ()
is a nullary tuple, (a, b)
is a binary tuple, (a, b, c)
is a ternary tuple, and so on, but what does that leave for the unary case? Saying a
is a unary tuple for any choice of a
is often not satisfactory, for example when we are building some typeclass instances like Data.Tuple.Select
, some type constructor is needed to act as the unambiguous key. So by adding e.g. Sel1
instances to Identity a
, it forces us to distinguish between (a, b)
(a two-tuple containing an a
and a b
), and Identity (a, b)
(a one-tuple containing a single (a, b)
value).
(Note that Data.Tuple.Select
defines its own type called OneTuple
instead of reusing Identity
, but it is isomorphic to Identity
—in fact, it's just a rename away—and I think it only exists to avoid a non-base
dependency.)
Identity
is joining base in 4.8 anyway, so that may soon be a historical artifact. Data.Sequence
uses an internal Elem
type (also isomorphic to Identity
) in these ways.
One real use-case is to be a (pure) base of monad transformers stack, e.g.
type Reader r = ReaderT r Identity