module Data.Lens.Partial.Common where
import Prelude hiding ((.), id, null, any, all)
import Control.Applicative
import Control.Category
import Control.Category.Product
import Data.Lens.Common (Lens(..))
import Control.Comonad.Trans.Store
import Data.Foldable (any, all)
import Data.Functor.Identity
import Data.Functor.Coproduct
import Data.Maybe
import Data.Monoid
newtype PartialLens a b = PLens (a -> Maybe (Store b a))
runPLens :: PartialLens a b -> a -> (Coproduct Identity (Store b)) a
runPLens (PLens f) a = maybe (left (Identity a)) right (f a)
instance Category PartialLens where
id = totalLens id
PLens f . PLens g = PLens $ \a -> do
(StoreT wba b) <- g a
(StoreT wcb c) <- f b
return (StoreT ((.) <$> wba <*> wcb) c)
null :: PartialLens a b
null = PLens (const Nothing)
totalLens :: Lens a b -> PartialLens a b
totalLens (Lens f) = PLens (Just . f)
getPL :: PartialLens a b -> a -> Maybe b
getPL (PLens f) a = pos <$> f a
getorPL :: PartialLens a b -> b -> a -> b
getorPL l b = fromMaybe b . getPL l
getorAPL :: Applicative f => PartialLens a b -> f b -> a -> f b
getorAPL l b = maybe b pure . getPL l
mergePL :: PartialLens a c -> PartialLens b c -> PartialLens (Either a b) c
(PLens f) `mergePL` (PLens g) =
PLens $ either (\a -> (fmap Left) <$> f a) (\b -> (fmap Right) <$> g b)
nullPL :: PartialLens a b -> a -> Bool
nullPL l = isNothing . getPL l
getorEmptyPL :: (Monoid o) => PartialLens a b -> (b -> o) -> a -> o
getorEmptyPL l p = maybe mempty p . getPL l
sumPL :: (Num c) => PartialLens a b -> (b -> c) -> a -> c
sumPL l p = getSum . getorEmptyPL l (Sum . p)
productPL :: (Num c) => PartialLens a b -> (b -> c) -> a -> c
productPL l p = getProduct . getorEmptyPL l (Product . p)
anyPL :: PartialLens a b -> (b -> Bool) -> a -> Bool
anyPL l p =
any p . getPL l
allPL :: PartialLens a b -> (b -> Bool) -> a -> Bool
allPL l p =
all p . getPL l
trySetPL :: PartialLens a b -> a -> Maybe (b -> a)
trySetPL (PLens f) a = flip peek <$> f a
setPL :: PartialLens a b -> b -> a -> a
setPL (PLens f) b a = maybe a (peek b) (f a)
modPL :: PartialLens a b -> (b -> b) -> a -> a
modPL (PLens f) g a = maybe a (peeks g) (f a)
infixr 0 ^$
(^$) :: PartialLens a b -> a -> Maybe b
(^$) = getPL
infixl 9 ^.
(^.) :: a -> PartialLens a b -> Maybe b
(^.) = flip getPL
infixr 4 ^=
(^=) :: PartialLens a b -> b -> a -> a
(^=) = setPL
infixr 4 ^%=
(^%=) :: PartialLens a b -> (b -> b) -> a -> a
(^%=) = modPL
infixr 4 ^%%=
(^%%=) :: Applicative f => PartialLens a b -> (b -> f b) -> a -> f a
PLens f ^%%= g = \a -> case f a of
Nothing -> pure a
Just (StoreT (Identity h) b) -> h <$> g b
infixr 4 ^+=, ^-=, ^*=
(^+=), (^-=), (^*=) :: Num b => PartialLens a b -> b -> a -> a
l ^+= n = l ^%= (+ n)
l ^-= n = l ^%= subtract n
l ^*= n = l ^%= (* n)
infixr 4 ^/=
(^/=) :: Fractional b => PartialLens a b -> b -> a -> a
l ^/= r = l ^%= (/ r)
justLens :: PartialLens (Maybe a) a
justLens = PLens $ \ma -> do
a <- ma
return (store Just a)
leftLens :: PartialLens (Either a b) a
leftLens = PLens $ either (Just . store Left) (const Nothing)
rightLens :: PartialLens (Either a b) b
rightLens = PLens $ either (const Nothing) (Just . store Right)
headLens :: PartialLens [a] a
headLens = PLens f
where
f [] = Nothing
f (h:t) = Just (store (:t) h)
tailLens :: PartialLens [a] [a]
tailLens = PLens f
where
f [] = Nothing
f (h:t) = Just (store (h:) t)
instance Tensor PartialLens where
PLens f *** PLens g =
PLens $ \(a, c) ->
do x <- f a
y <- g c
return $ store (\(b, d) -> (peek b x, peek d y)) (pos x, pos y)