haskell / haskell/transformers

Add a lifted identity functor

Open
#64 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Haskell
Stars
5
Forks
10
Avg merge
2h 21m
Merged PRs (30d)
1

Description

[original issue 52 by @treeowl]


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?

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.