sebastiaanvisser/fclabels — Issue #7: Possibly faster Point
Author: sjoerdvisscher
Created: 2011-12-31 13:07:12+00:00
State: open

```haskell
newtype Point m f i o = Point { runPoint :: f -> m (i -> m f, o) }

getSetPoint :: Monad m => (f -> m o) -> (i -> f -> m f) -> Point m f i o
getSetPoint g s = Point $ \f -> g f >>= \o -> return (flip s f, o)

_get :: Monad m => Point m f i o -> f -> m o
_get p f = liftM snd $ runPoint p f

_set :: Monad m => Point m f i o -> i -> f -> m f
_set p i f = runPoint p f >>= \(s, _) -> s i

_modify :: Monad m => Point m f i o -> (o -> m i) -> f -> m f
_modify p m f = runPoint p f >>= \(s, o) -> m o >>= s

instance Monad m => Functor (Point m f i) where
fmap f = Point . fmap (liftM (fmap f)) . runPoint

instance Monad m => Applicative (Point m f i) where
pure a = Point $ \f -> return (const (return f), a)
pf <*> pa = getSetPoint (\f -> _get pf f `ap` _get pa f) (\i -> _set pf i >=> _set pa i)

bimap :: Monad m => (o' -> m o) -> (i -> m i') -> Point m f i' o' -> Point m f i o
bimap g h p = Point . runKleisli $ (arr (h >=>) *** Kleisli g) . Kleisli (runPoint p)
```