forbidden-fruit-0.1.0: src/Control/Imperative/Zoom.hs
-------------------------------------------------------------
-- |
-- Module : Control.Imperative.Zoom
-- Copyright : (C) 2015, Yu Fukuzawa
-- License : BSD3
-- Maintainer : minpou.primer@email.com
-- Stability : experimental
-- Portability : portable
--
-----------------------------------------------------------
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
module Control.Imperative.Zoom
( zoomR
, Traversal'
)
where
import Control.Applicative (Applicative, Const (..))
import Control.Imperative.Internal
import Control.Monad
import Data.Functor.Identity (Identity (..))
import Data.Maybe (fromMaybe)
import Data.Monoid (First (..))
-- | See <http://hackage.haskell.org/package/lens/docs/Control-Lens-Traversal.html>.
type Traversal' s a = Applicative f => (a -> f a) -> s -> f s
unsafePreview :: Traversal' s a -> s -> a
unsafePreview l s = fromMaybe (error "empty value") $ getFirst $ getConst $ l (Const . First . Just) s
{-# INLINE unsafePreview #-}
set' :: Traversal' s a -> a -> s -> s
set' l x = runIdentity . l (const (Identity x))
{-# INLINE set' #-}
-- | Zoom in on stored value in the 'Ref'.
zoomR :: Monad m => Traversal' s a -> Ref m s -> Ref m a
zoomR l r = Ref
{ get = liftM (unsafePreview l) $ get r
, set = \x -> get r >>= \s -> let t = set' l x s in t `seq` set r t
}
{-# INLINE zoomR #-}