Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of the IdentityT transformer?

While looking through the transformers package, I found this monad transformer called IdentityT.

Although I understand how the Identity monad is used (e.g. State is just an alias for StateT Identity) and how monad transformers work in general, I have no idea how that relates to IdentityT.

Since it's not in the MTL, I'm guessing it was added in there just for completeness and has no practical use. Is that correct?

like image 483
Lambda Fairy Avatar asked Feb 03 '12 02:02

Lambda Fairy


2 Answers

Well the linked documentation does say

This is useful for functions parameterized by a monad transformer.

Though I'm not aware of any situations where this is actually the case. Theoretically if you have a function like foo :: (MonadTrans t, Monad m) => t m a -> b for some useful b, then you might want to be able to "dumb it down" to essentially m a -> b by using t = IdentityT.

But IdentityT is to MonadTrans what Identity is to Monad. It is the "pass-through" transformer, as Identity is the "pass-through" monad. Just check out the source; it's rather simple. IdentityT SomeMonad a should behave identically to SomeMonad a, the only difference being the presence of an extra newtype (which, of course, is removed at compile time)

like image 142
Dan Burton Avatar answered Sep 18 '22 05:09

Dan Burton


There's a proposed usage here (presumably the origin of IdentityT: http://www.haskell.org/pipermail/libraries/2007-June/007563.html

The main use seems to be to allow flexibility at the source code level, e.g. someone can edit the source to xmonad and substitute their own UserT without editing too much code.

I tried to see how that could work for a library - you can use it to provide a placeholder for inserting a monad in the middle of a stack, I'm not sure of a great case for that though. Here's my contrived example:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Main where

import Control.Monad.State
import Control.Monad.List
import Control.Monad.Reader

type X m a = StateT Int (m IO) a

something :: (Monad (m IO), MonadIO (m IO)) => (m IO) Int -> X m Int 
something a = do
        x <- lift a
        put (x + 1)

        liftIO $ print x
        return x



listSomething = something $ ListT (mapM return [1,2,3,4])
plainSomething = return 5 :: IdentityT IO Int

main = do 
    x <- runListT (execStateT listSomething 3)
    print x 

    y <- runIdentityT (execStateT plainSomething 3)
    print y

runIdentity $ mapM (return . (+1)) [1..100]
like image 34
Oliver Avatar answered Sep 19 '22 05:09

Oliver