123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
- {-# LANGUAGE RankNTypes #-}
- {-# LANGUAGE LambdaCase #-}
- module Codec.ActivityStream.LensInternal where
- import Data.Aeson as Aeson
- import qualified Data.HashMap.Strict as HM
- import Data.Maybe (fromJust)
- import Data.Text (Text)
- -- This way, we don't have to import lens... but we can still export lenses!
- newtype Const a b = Const { fromConst :: a }
- instance Functor (Const a) where fmap f (Const x) = Const x
- -- We need these to write get and set
- newtype Id a = Id { fromId :: a }
- instance Functor Id where fmap f (Id x) = Id (f x)
- -- | This is the same type alias as in @Control.Lens@, and so can be used
- -- anywhere lenses are needed.
- type Lens' a b = forall f. Functor f => (b -> f b) -> (a -> f a)
- get :: Lens' a b -> a -> b
- get lens a = fromConst (lens Const a)
- set :: Lens' a b -> b -> a -> a
- set lens x a = fromId (lens (const Id x) a)
- makeLens :: (a -> b) -> (b -> a -> a) -> Lens' a b
- makeLens get set f a = (`set` a) `fmap` f (get a)
- fromJSON' :: FromJSON a => Aeson.Value -> Maybe a
- fromJSON' v = case fromJSON v of
- Success a -> Just a
- Error _ -> Nothing
- -- Create a lens into an Aeson object wrapper that takes and
- -- returns a Maybe value
- makeAesonLensMb :: (FromJSON v, ToJSON v)
- => Text -> Lens' c Aeson.Object -> Lens' c (Maybe v)
- makeAesonLensMb key fromObj = fromObj . lens
- where lens = makeLens
- (\ o -> HM.lookup key o >>= fromJSON')
- (\case Just v -> HM.insert key (toJSON v)
- Nothing -> HM.delete key)
- -- Create a lens into an Aeson object wrapper
- makeAesonLens :: (FromJSON v, ToJSON v)
- => Text -> Lens' c Aeson.Object -> Lens' c v
- makeAesonLens key fromObj = fromObj . lens
- where lens = makeLens
- (\ o -> fromJust (HM.lookup key o >>= fromJSON'))
- (\ v o -> HM.insert key (toJSON v) o)
|