aboutsummaryrefslogtreecommitdiff
path: root/ch15_15.5.1.example.hs
diff options
context:
space:
mode:
authorPaul Oliver <contact@pauloliver.dev>2025-01-03 11:01:20 -0800
committerPaul Oliver <contact@pauloliver.dev>2025-01-05 09:59:10 -0800
commit6a0d7f5c434c3564d0119befb6799fd77581050a (patch)
treef20bc998290211d2a895523417ad32e297b31af0 /ch15_15.5.1.example.hs
InitialHEADmaster
Diffstat (limited to 'ch15_15.5.1.example.hs')
-rw-r--r--ch15_15.5.1.example.hs77
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