diff options
Diffstat (limited to 'ch15_15.5.1.example.hs')
-rw-r--r-- | ch15_15.5.1.example.hs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/ch15_15.5.1.example.hs b/ch15_15.5.1.example.hs new file mode 100644 index 0000000..b2daec1 --- /dev/null +++ b/ch15_15.5.1.example.hs @@ -0,0 +1,77 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeFamilies #-} + +import Data.Aeson (Value, object, (.=)) +import Data.Constraint (Dict (Dict)) +import Data.Kind (Type) +import Data.Maybe (mapMaybe) +import Data.Singletons (Sing, SingI, sing) +import Data.Singletons.Base.TH (genSingletons, singDecideInstance) +import Data.Singletons.Decide qualified as D + +data Sigma (f :: k -> Type) where + Sigma :: Sing a -> f a -> Sigma f + +withSigma :: (forall (a :: k). Sing a -> f a -> r) -> Sigma f -> r +withSigma c (Sigma s f) = c s f + +toSigma :: SingI a => f a -> Sigma f +toSigma = Sigma sing + +fromSigma + :: forall k (a :: k) (f :: k -> Type) + . (SingI a, D.SDecide k) + => Sigma f + -> Maybe (f a) +fromSigma (Sigma s f) = + case s D.%~ sing @a of + D.Proved D.Refl -> Just f + D.Disproved _ -> Nothing + +class Dict1 c (f :: k -> Type) where + dict1 :: Sing (a :: k) -> Dict (c (f a)) + +data LogType = JsonMsg | TextMsg deriving (Eq, Ord, Show) + +$(genSingletons [''LogType]) +$(singDecideInstance ''LogType) + +data family LogMsg (msg :: LogType) + +newtype instance LogMsg 'JsonMsg = Json Value deriving (Eq, Show) + +newtype instance LogMsg 'TextMsg = Text String deriving (Eq, Show) + +instance + ( c (LogMsg 'JsonMsg) + , c (LogMsg 'TextMsg) + ) + => Dict1 c LogMsg + where + dict1 SJsonMsg = Dict + dict1 STextMsg = Dict + +catSigmas + :: forall k (a :: k) f + . ( SingI a + , D.SDecide k + ) + => [Sigma f] + -> [f a] +catSigmas = mapMaybe fromSigma + +logs :: [Sigma LogMsg] +logs = + [ toSigma $ Text "hello" + , toSigma $ Json $ object ["world" .= (5 :: Int)] + , toSigma $ Text "structured logging" + ] + +jsonLogs :: [LogMsg 'JsonMsg] +jsonLogs = catSigmas logs + +textLogs :: [LogMsg 'TextMsg] +textLogs = catSigmas logs |