Skip to content

Instantly share code, notes, and snippets.

@frasertweedale
Created August 15, 2024 04:11
Show Gist options
  • Save frasertweedale/76914422e62d92c2507e0c2b55acf3b3 to your computer and use it in GitHub Desktop.
Save frasertweedale/76914422e62d92c2507e0c2b55acf3b3 to your computer and use it in GitHub Desktop.
module Experiement where
import Data.Kind (Type)
import Data.Proxy (Proxy(..))
data VariantA
data VariantB
data VariantC
data Object (a :: Type) = Object
deriving (Show)
--
-- Option 1: explicit discriminated union
--
data WrappedObject
= WrappedObjectA (Object VariantA)
| WrappedObjectB (Object VariantB)
| WrappedObjectC (Object VariantC)
go1 :: String -> WrappedObject
go1 variant = case variant of
"a" -> WrappedObjectA Object
"b" -> WrappedObjectB Object
"c" -> WrappedObjectC Object
_ -> error "unrecognised variant"
main1 :: IO ()
main1 = do
let obj = go1 "a"
case obj of
WrappedObjectA _ -> putStrLn "a"
WrappedObjectB _ -> putStrLn "b"
WrappedObjectC _ -> putStrLn "c"
--
-- Option 2: if all behaviour for each variant can be
-- defined via a type class interface, you can use a GADT
-- to monomorphise.
--
class Variant a where
variantName :: Proxy a -> String
instance Variant VariantA where
variantName _ = "a"
instance Variant VariantB where
variantName _ = "b"
instance Variant VariantC where
variantName _ = "c"
data Object' where
Object' :: (Variant a) => Object a -> Object'
go2 :: String -> Object'
go2 variant = case variant of
"a" -> Object' (Object :: Object VariantA)
"b" -> Object' (Object :: Object VariantB)
"c" -> Object' (Object :: Object VariantC)
_ -> error "unrecognised variant"
main2 :: IO ()
main2 = do
let obj' = go2 "b"
case obj' of
Object' obj -> putStrLn (variantName (variantProxy obj))
variantProxy :: forall t a. t a -> Proxy a
variantProxy _ = Proxy @a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment