1 {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, ConstraintKinds, TemplateHaskell, TypeSynonymInstances, LiberalTypeSynonyms #-}
    2 module Databrary.Has
    3   ( Has(..)
    4   , MonadHas
    5   , peek
    6   , peeks
    7   , focusIO
    8   ) where
    9 
   10 import Control.Monad.IO.Class (MonadIO(..))
   11 import Control.Monad.Reader (MonadReader, ReaderT(..), reader)
   12 
   13 class Has a c where
   14   view :: c -> a
   15 
   16 instance Has a a where
   17   view = id
   18 
   19 type MonadHas a s m = (Functor m, Applicative m, MonadReader s m, Has a s)
   20 
   21 {-# INLINE peek #-}
   22 peek :: (MonadReader c m, Has a c) => m a
   23 peek = reader view
   24 
   25 {-# INLINE peeks #-}
   26 peeks :: (MonadReader c m, Has a c) => (a -> b) -> m b
   27 peeks f = reader (f . view)
   28 
   29 {-# INLINE focusReader #-}
   30 focusReader :: Has a c => (a -> m b) -> ReaderT c m b
   31 focusReader f = ReaderT (f . view)
   32 
   33 {-# INLINE[2] focusIO #-}
   34 focusIO :: (MonadIO m, MonadHas a c m) => (a -> IO b) -> m b
   35 focusIO f = liftIO . f =<< peek
   36 
   37 {-# RULES "focusIO/ReaderT" focusIO = focusReader #-}