module Hans.Lens (
Lens, Lens',
lens,
Getting,
Getter,
view,
to,
ASetter, ASetter',
set,
over,
modify,
bit,
byte,
) where
import qualified Control.Applicative as A
import qualified Data.Bits as B
import Data.Word (Word8)
import MonadLib (Id,runId)
type Lens s t a b = forall f. Functor f => (a -> f b) -> (s -> f t)
type Lens' s a = Lens s s a a
lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
lens get upd = \ f s -> upd s `fmap` f (get s)
type Getting r s a = (a -> Const r a) -> (s -> Const r s)
type Getter s a = forall r. Getting r s a
newtype Const r a = Const { runConst :: r } deriving Functor
castConst' :: (b -> a) -> Const r a -> Const r b
castConst' _ (Const r) = Const r
view :: Getting a s a -> s -> a
view l = \ s -> runConst (l Const s)
to :: (s -> a) -> Getting r s a
to f = \ l s -> castConst' f (l (f s))
type ASetter s t a b = (a -> Id b) -> (s -> Id t)
type ASetter' s a = ASetter s s a a
set :: Lens s t a b -> b -> s -> t
set l b = \ s -> runId (l (\ _ -> A.pure b) s)
over :: ASetter s t a b -> (a -> b) -> (s -> t)
over l f = \ s -> runId (l (A.pure . f) s)
newtype Modify r a = Modify { runModify :: (a,r) }
instance Functor (Modify r) where
fmap f = \ (Modify (a,r)) -> Modify (f a, r)
modify :: Lens s t a b -> (a -> (b,r)) -> (s -> (t,r))
modify l f = \ s -> runModify (l (\ a -> Modify (f a)) s)
bit :: B.Bits a => Int -> Lens' a Bool
bit n = lens get upd
where
get a = B.testBit a n
upd a True = B.setBit a n
upd a False = B.clearBit a n
byte :: (Integral a, B.Bits a) => Int -> Lens' a Word8
byte n = lens get upd
where
sh = n * 8
get a = fromIntegral (a `B.shiftR` sh)
upd a b = a B..|. (fromIntegral b `B.shiftL` sh)