{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE Rank2Types #-}
module Toml.BiMap
(
BiMap (..)
, invert
, iso
, prism
, matchValueForward
, mkAnyValueBiMap
, _Array
, _Bool
, _Double
, _Integer
, _String
, _Text
, _TextToString
, _Left
, _Right
, toMArray
) where
import Control.Arrow ((>>>))
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
import qualified Data.Text as T
data BiMap a b = BiMap
{ forward :: a -> Maybe b
, backward :: b -> Maybe a
}
instance Cat.Category BiMap where
id :: BiMap a a
id = BiMap Just Just
(.) :: BiMap b c -> BiMap a b -> BiMap a c
bc . ab = BiMap
{ forward = forward ab >=> forward bc
, backward = backward bc >=> backward ab
}
invert :: BiMap a b -> BiMap b a
invert (BiMap f g) = BiMap g f
iso :: (a -> b) -> (b -> a) -> BiMap a b
iso f g = BiMap (Just . f) (Just . g)
prism :: (object -> Maybe field) -> (field -> object) -> BiMap object field
prism preview review = BiMap preview (Just . review)
_Left :: BiMap l (Either l r)
_Left = invert $ prism (either Just (const Nothing)) Left
_Right :: BiMap r (Either l r)
_Right = invert $ prism (either (const Nothing) Just) Right
mkAnyValueBiMap :: (forall t . Value t -> Maybe a)
-> (a -> Value tag)
-> BiMap AnyValue a
mkAnyValueBiMap matchValue toValue =
prism (\(AnyValue value) -> matchValue value) (AnyValue . toValue)
matchValueForward :: BiMap AnyValue a -> Value t -> Maybe a
matchValueForward = liftMatch . forward
_Bool :: BiMap AnyValue Bool
_Bool = mkAnyValueBiMap matchBool Bool
_Integer :: BiMap AnyValue Integer
_Integer = mkAnyValueBiMap matchInteger Integer
_Double :: BiMap AnyValue Double
_Double = mkAnyValueBiMap matchDouble Double
_Text :: BiMap AnyValue Text
_Text = mkAnyValueBiMap matchText Text
_TextToString :: BiMap Text String
_TextToString = iso T.unpack T.pack
_String :: BiMap AnyValue String
_String = _Text >>> _TextToString
_Array :: BiMap AnyValue a -> BiMap AnyValue [a]
_Array elementBimap = BiMap
{ forward = \(AnyValue val) -> matchArray (forward elementBimap) val
, backward = mapM (backward elementBimap) >=> fmap AnyValue . toMArray
}
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)