------------------------------------------------------------- -- | -- 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 . 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 #-}