concrete functor and monad transformers

#52Add a lifted identity functor

Feel free to change the lousy title of this ticket. The following very boring type is often useful when laziness needs to be managed in a fine-grained manner:

data Box a = Box {unBox :: a}
  deriving (Show, Read, Eq, Ord)
instance Functor Box where
  fmap f (Box a) = Box (f a)
instance Applicative Box where
  Box f <*> Box x = Box (f x)
instance Monad Box where
  Box x >>= f = f x
-- etc

For example, you can write a strict mapping function like this:

strictMap :: Traversable t => (a -> b) -> t a -> t b
strictMap f = unBox . traverse (\a -> Box $! f a)

To write a strict traversing function, you need to take it up a level, to the lifted identity monad transformer:

newtype BoxT m a = BoxT {runBoxT :: m (Box a)}

instance Functor m => Functor (BoxT m) where
  fmap f (BoxT mba) = BoxT (fmap (fmap f) mba)

instance Applicative m => Applicative (BoxT m) where
  pure = BoxT . pure . Box
  BoxT m <*> BoxT n = BoxT $ (<*>) <$> m <*> n

instance Monad m => Monad (BoxT m) where
  BoxT m >>= f = BoxT $ m >>= \(Box a) -> runBoxT (f a)

instance MonadTrans BoxT where
  lift = BoxT . fmap Box

Now you can write

strictTraverse :: (Traversable t, Applicative f)
          => (a -> f b) -> t a -> f (t b)
strictTraverse f = fmap unBox . runBoxT . traverse (\a -> BoxT ((Box $!) <$> f a))

Do you think it would make sense to add such types to transformers?