tomland-0.5.0: src/Toml/Type/AnyValue.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
module Toml.Type.AnyValue
( AnyValue (..)
, reifyAnyValues
, toMArray
-- * Matching
, liftMatch
, matchBool
, matchInteger
, matchDouble
, matchText
, matchDate
, matchArray
) where
import Control.DeepSeq (NFData, rnf)
import Data.Text (Text)
import Data.Type.Equality ((:~:) (..))
import Toml.Type.Value (DateTime, TValue (..), TypeMismatchError, Value (..), sameValue)
-- | Existential wrapper for 'Value'.
data AnyValue = forall (t :: TValue) . AnyValue (Value t)
instance Show AnyValue where
show (AnyValue v) = show v
instance Eq AnyValue where
(AnyValue val1) == (AnyValue val2) = case sameValue val1 val2 of
Right Refl -> val1 == val2
Left _ -> False
instance NFData AnyValue where
rnf (AnyValue val) = rnf val
----------------------------------------------------------------------------
-- Matching functions for values
----------------------------------------------------------------------------
-- | Extract 'Bool' from 'Value'.
matchBool :: Value t -> Maybe Bool
matchBool (Bool b) = Just b
matchBool _ = Nothing
-- | Extract 'Integer' from 'Value'.
matchInteger :: Value t -> Maybe Integer
matchInteger (Integer n) = Just n
matchInteger _ = Nothing
-- | Extract 'Double' from 'Value'.
matchDouble :: Value t -> Maybe Double
matchDouble (Double f) = Just f
matchDouble _ = Nothing
-- | Extract 'Text' from 'Value'.
matchText :: Value t -> Maybe Text
matchText (Text s) = Just s
matchText _ = Nothing
-- | Extract 'DateTime' from 'Value'.
matchDate :: Value t -> Maybe DateTime
matchDate (Date d) = Just d
matchDate _ = Nothing
-- | Extract list of elements of type @a@ from array.
matchArray :: (AnyValue -> Maybe a) -> Value t -> Maybe [a]
matchArray matchValue (Array a) = mapM (liftMatch matchValue) a
matchArray _ _ = Nothing
liftMatch :: (AnyValue -> Maybe a) -> (Value t -> Maybe a)
liftMatch fromAnyValue = fromAnyValue . AnyValue
-- | Checks whether all elements inside given list of 'AnyValue' have the same
-- type as given 'Value'. Returns list of @Value t@ without given 'Value'.
reifyAnyValues :: Value t -> [AnyValue] -> Either TypeMismatchError [Value t]
reifyAnyValues _ [] = Right []
reifyAnyValues v (AnyValue av : xs) = sameValue v av >>= \Refl -> (av :) <$> reifyAnyValues v xs
-- | Function for creating 'Array' from list of 'AnyValue'.
toMArray :: [AnyValue] -> Maybe (Value 'TArray)
toMArray [] = Just $ Array []
toMArray (AnyValue x : xs) = case reifyAnyValues x xs of
Left _ -> Nothing
Right vals -> Just $ Array (x : vals)