{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Data.GI.Base.DynVal
( DynVal(..), DVKey(..), ModelProxy(..), dvKeys, dvRead,
modelProxyCurrentValue, modelProxyRegisterHandler, modelProxyUpdate) where
import GHC.Records (HasField(..))
import qualified GHC.TypeLits as TL
import Data.Proxy (Proxy(..))
import qualified Data.Set as S
import Data.String (IsString(..))
import qualified Data.Text as T
data DVKey = DVKeyDirect [T.Text]
| DVKeyDerived (S.Set [T.Text])
deriving (DVKey -> DVKey -> Bool
(DVKey -> DVKey -> Bool) -> (DVKey -> DVKey -> Bool) -> Eq DVKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DVKey -> DVKey -> Bool
== :: DVKey -> DVKey -> Bool
$c/= :: DVKey -> DVKey -> Bool
/= :: DVKey -> DVKey -> Bool
Eq, Eq DVKey
Eq DVKey =>
(DVKey -> DVKey -> Ordering)
-> (DVKey -> DVKey -> Bool)
-> (DVKey -> DVKey -> Bool)
-> (DVKey -> DVKey -> Bool)
-> (DVKey -> DVKey -> Bool)
-> (DVKey -> DVKey -> DVKey)
-> (DVKey -> DVKey -> DVKey)
-> Ord DVKey
DVKey -> DVKey -> Bool
DVKey -> DVKey -> Ordering
DVKey -> DVKey -> DVKey
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: DVKey -> DVKey -> Ordering
compare :: DVKey -> DVKey -> Ordering
$c< :: DVKey -> DVKey -> Bool
< :: DVKey -> DVKey -> Bool
$c<= :: DVKey -> DVKey -> Bool
<= :: DVKey -> DVKey -> Bool
$c> :: DVKey -> DVKey -> Bool
> :: DVKey -> DVKey -> Bool
$c>= :: DVKey -> DVKey -> Bool
>= :: DVKey -> DVKey -> Bool
$cmax :: DVKey -> DVKey -> DVKey
max :: DVKey -> DVKey -> DVKey
$cmin :: DVKey -> DVKey -> DVKey
min :: DVKey -> DVKey -> DVKey
Ord, Int -> DVKey -> ShowS
[DVKey] -> ShowS
DVKey -> String
(Int -> DVKey -> ShowS)
-> (DVKey -> String) -> ([DVKey] -> ShowS) -> Show DVKey
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DVKey -> ShowS
showsPrec :: Int -> DVKey -> ShowS
$cshow :: DVKey -> String
show :: DVKey -> String
$cshowList :: [DVKey] -> ShowS
showList :: [DVKey] -> ShowS
Show)
data DynVal model a = DynVal DVKey (model -> a)
dvKeys :: DynVal model a -> DVKey
dvKeys :: forall model a. DynVal model a -> DVKey
dvKeys (DynVal DVKey
s model -> a
_) = DVKey
s
dvRead :: DynVal model a -> model -> a
dvRead :: forall model a. DynVal model a -> model -> a
dvRead (DynVal DVKey
_ model -> a
r) = model -> a
r
toDerived :: DVKey -> DVKey
toDerived :: DVKey -> DVKey
toDerived (DVKeyDirect [Text]
d) = Set [Text] -> DVKey
DVKeyDerived ([Text] -> Set [Text]
forall a. a -> Set a
S.singleton [Text]
d)
toDerived DVKey
derived = DVKey
derived
instance Semigroup DVKey where
DVKeyDirect [Text]
a <> :: DVKey -> DVKey -> DVKey
<> DVKeyDirect [Text]
b = Set [Text] -> DVKey
DVKeyDerived (Set [Text] -> DVKey) -> Set [Text] -> DVKey
forall a b. (a -> b) -> a -> b
$ [[Text]] -> Set [Text]
forall a. Ord a => [a] -> Set a
S.fromList [[Text]
a,[Text]
b]
(DVKeyDirect [Text]
a) <> (DVKeyDerived Set [Text]
b) =
Set [Text] -> DVKey
DVKeyDerived (Set [Text] -> DVKey) -> Set [Text] -> DVKey
forall a b. (a -> b) -> a -> b
$ [Text] -> Set [Text] -> Set [Text]
forall a. Ord a => a -> Set a -> Set a
S.insert [Text]
a Set [Text]
b
(DVKeyDerived Set [Text]
a) <> (DVKeyDirect [Text]
b) =
Set [Text] -> DVKey
DVKeyDerived (Set [Text] -> DVKey) -> Set [Text] -> DVKey
forall a b. (a -> b) -> a -> b
$ [Text] -> Set [Text] -> Set [Text]
forall a. Ord a => a -> Set a -> Set a
S.insert [Text]
b Set [Text]
a
(DVKeyDerived Set [Text]
a) <> (DVKeyDerived Set [Text]
b) =
Set [Text] -> DVKey
DVKeyDerived (Set [Text] -> DVKey) -> Set [Text] -> DVKey
forall a b. (a -> b) -> a -> b
$ Set [Text] -> Set [Text] -> Set [Text]
forall a. Ord a => Set a -> Set a -> Set a
S.union Set [Text]
a Set [Text]
b
instance Functor (DynVal model) where
fmap :: forall a b. (a -> b) -> DynVal model a -> DynVal model b
fmap a -> b
f DynVal model a
dv = DVKey -> (model -> b) -> DynVal model b
forall model a. DVKey -> (model -> a) -> DynVal model a
DynVal (DVKey -> DVKey
toDerived (DVKey -> DVKey) -> DVKey -> DVKey
forall a b. (a -> b) -> a -> b
$ DynVal model a -> DVKey
forall model a. DynVal model a -> DVKey
dvKeys DynVal model a
dv) (a -> b
f (a -> b) -> (model -> a) -> model -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DynVal model a -> model -> a
forall model a. DynVal model a -> model -> a
dvRead DynVal model a
dv)
instance Applicative (DynVal model) where
pure :: forall a. a -> DynVal model a
pure a
x = DVKey -> (model -> a) -> DynVal model a
forall model a. DVKey -> (model -> a) -> DynVal model a
DynVal (Set [Text] -> DVKey
DVKeyDerived Set [Text]
forall a. Set a
S.empty) (a -> model -> a
forall a b. a -> b -> a
const a
x)
DynVal model (a -> b)
dF <*> :: forall a b.
DynVal model (a -> b) -> DynVal model a -> DynVal model b
<*> DynVal model a
dA = DVKey -> (model -> b) -> DynVal model b
forall model a. DVKey -> (model -> a) -> DynVal model a
DynVal (DynVal model (a -> b) -> DVKey
forall model a. DynVal model a -> DVKey
dvKeys DynVal model (a -> b)
dF DVKey -> DVKey -> DVKey
forall a. Semigroup a => a -> a -> a
<> DynVal model a -> DVKey
forall model a. DynVal model a -> DVKey
dvKeys DynVal model a
dA)
(\model
m -> let f :: a -> b
f = DynVal model (a -> b) -> model -> a -> b
forall model a. DynVal model a -> model -> a
dvRead DynVal model (a -> b)
dF model
m
in a -> b
f (DynVal model a -> model -> a
forall model a. DynVal model a -> model -> a
dvRead DynVal model a
dA model
m))
instance IsString (DynVal model T.Text) where
fromString :: String -> DynVal model Text
fromString String
s = Text -> DynVal model Text
forall a. a -> DynVal model a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> Text
T.pack String
s)
data ModelProxy model = ModelProxy (IO model) (DVKey -> (model -> IO ()) -> IO ()) ([T.Text] -> (model -> Maybe model) -> IO ())
modelProxyCurrentValue :: ModelProxy model -> IO model
modelProxyCurrentValue :: forall model. ModelProxy model -> IO model
modelProxyCurrentValue (ModelProxy IO model
m DVKey -> (model -> IO ()) -> IO ()
_ [Text] -> (model -> Maybe model) -> IO ()
_) = IO model
m
modelProxyRegisterHandler :: ModelProxy model -> DVKey -> (model -> IO ()) -> IO ()
modelProxyRegisterHandler :: forall model.
ModelProxy model -> DVKey -> (model -> IO ()) -> IO ()
modelProxyRegisterHandler (ModelProxy IO model
_ DVKey -> (model -> IO ()) -> IO ()
r [Text] -> (model -> Maybe model) -> IO ()
_) = DVKey -> (model -> IO ()) -> IO ()
r
modelProxyUpdate :: ModelProxy model -> [T.Text] -> (model -> Maybe model)
-> IO ()
modelProxyUpdate :: forall model.
ModelProxy model -> [Text] -> (model -> Maybe model) -> IO ()
modelProxyUpdate (ModelProxy IO model
_ DVKey -> (model -> IO ()) -> IO ()
_ [Text] -> (model -> Maybe model) -> IO ()
u) = [Text] -> (model -> Maybe model) -> IO ()
u
instance (HasField fieldName field a,
TL.KnownSymbol fieldName) =>
HasField fieldName (DynVal model field) (DynVal model a) where
getField :: DynVal model field -> DynVal model a
getField DynVal model field
dv = let fn :: Text
fn = String -> Text
T.pack (String -> Text)
-> (Proxy fieldName -> String) -> Proxy fieldName -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy fieldName -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
TL.symbolVal (Proxy fieldName -> Text) -> Proxy fieldName -> Text
forall a b. (a -> b) -> a -> b
$ (Proxy fieldName
forall {k} (t :: k). Proxy t
Proxy :: Proxy fieldName)
key :: DVKey
key = case DynVal model field -> DVKey
forall model a. DynVal model a -> DVKey
dvKeys DynVal model field
dv of
derived :: DVKey
derived@(DVKeyDerived Set [Text]
_) -> DVKey
derived
DVKeyDirect [Text]
direct -> [Text] -> DVKey
DVKeyDirect ([Text]
direct [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> [Text
fn])
in DVKey -> (model -> a) -> DynVal model a
forall model a. DVKey -> (model -> a) -> DynVal model a
DynVal DVKey
key (forall {k} (x :: k) r a. HasField x r a => r -> a
forall (x :: Symbol) r a. HasField x r a => r -> a
getField @fieldName (field -> a) -> (model -> field) -> model -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DynVal model field -> model -> field
forall model a. DynVal model a -> model -> a
dvRead DynVal model field
dv)