{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE Rank2Types #-}
module Toml.Prism
(
Prism (..)
, match
, mkAnyValuePrism
, _Bool
, _Integer
, _Double
, _Text
, _Array
, unsafeArray
) where
import Control.Monad ((>=>))
import Data.Text (Text)
import Toml.Type (AnyValue (..), TValue (TArray), Value (..), liftMatch, matchArray, matchBool,
matchDouble, matchInteger, matchText, reifyAnyValues)
import qualified Control.Category as Cat
data Prism object field = Prism
{ preview :: object -> Maybe field
, review :: field -> object
}
instance Cat.Category Prism where
id :: Prism object object
id = Prism { preview = Just, review = id }
(.) :: Prism field subfield -> Prism object field -> Prism object subfield
fieldPrism . objectPrism = Prism
{ preview = preview objectPrism >=> preview fieldPrism
, review = review objectPrism . review fieldPrism
}
mkAnyValuePrism :: (forall t . Value t -> Maybe a)
-> (a -> Value tag)
-> Prism AnyValue a
mkAnyValuePrism matchValue toValue = Prism
{ review = AnyValue . toValue
, preview = \(AnyValue value) -> matchValue value
}
match :: Prism AnyValue a -> Value t -> Maybe a
match = liftMatch . preview
_Bool :: Prism AnyValue Bool
_Bool = mkAnyValuePrism matchBool Bool
_Integer :: Prism AnyValue Integer
_Integer = mkAnyValuePrism matchInteger Integer
_Double :: Prism AnyValue Double
_Double = mkAnyValuePrism matchDouble Double
_Text :: Prism AnyValue Text
_Text = mkAnyValuePrism matchText Text
_Array :: Prism AnyValue a -> Prism AnyValue [a]
_Array elementPrism = mkAnyValuePrism (matchArray $ preview elementPrism)
(unsafeArray . map (review elementPrism))
unsafeArray :: [AnyValue] -> Value 'TArray
unsafeArray [] = Array []
unsafeArray (AnyValue x : xs) = case reifyAnyValues x xs of
Left err -> error $ "Can't create Array from list AnyValues: " ++ show err
Right vals -> Array (x : vals)