LensInternal.hs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. {-# LANGUAGE RankNTypes #-}
  2. {-# LANGUAGE LambdaCase #-}
  3. module Codec.ActivityStream.LensInternal where
  4. import Data.Aeson as Aeson
  5. import qualified Data.HashMap.Strict as HM
  6. import Data.Maybe (fromJust)
  7. import Data.Text (Text)
  8. -- This way, we don't have to import lens... but we can still export lenses!
  9. newtype Const a b = Const { fromConst :: a }
  10. instance Functor (Const a) where fmap f (Const x) = Const x
  11. -- We need these to write get and set
  12. newtype Id a = Id { fromId :: a }
  13. instance Functor Id where fmap f (Id x) = Id (f x)
  14. -- | This is the same type alias as in @Control.Lens@, and so can be used
  15. -- anywhere lenses are needed.
  16. type Lens' a b = forall f. Functor f => (b -> f b) -> (a -> f a)
  17. get :: Lens' a b -> a -> b
  18. get lens a = fromConst (lens Const a)
  19. set :: Lens' a b -> b -> a -> a
  20. set lens x a = fromId (lens (const Id x) a)
  21. makeLens :: (a -> b) -> (b -> a -> a) -> Lens' a b
  22. makeLens get set f a = (`set` a) `fmap` f (get a)
  23. fromJSON' :: FromJSON a => Aeson.Value -> Maybe a
  24. fromJSON' v = case fromJSON v of
  25. Success a -> Just a
  26. Error _ -> Nothing
  27. -- Create a lens into an Aeson object wrapper that takes and
  28. -- returns a Maybe value
  29. makeAesonLensMb :: (FromJSON v, ToJSON v)
  30. => Text -> Lens' c Aeson.Object -> Lens' c (Maybe v)
  31. makeAesonLensMb key fromObj = fromObj . lens
  32. where lens = makeLens
  33. (\ o -> HM.lookup key o >>= fromJSON')
  34. (\case Just v -> HM.insert key (toJSON v)
  35. Nothing -> HM.delete key)
  36. -- Create a lens into an Aeson object wrapper
  37. makeAesonLens :: (FromJSON v, ToJSON v)
  38. => Text -> Lens' c Aeson.Object -> Lens' c v
  39. makeAesonLens key fromObj = fromObj . lens
  40. where lens = makeLens
  41. (\ o -> fromJust (HM.lookup key o >>= fromJSON'))
  42. (\ v o -> HM.insert key (toJSON v) o)