{-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE ScopedTypeVariables #-} module Main where import System.IO.Unsafe (unsafePerformIO) data Mode = A | B data Settings (mode :: Mode) where SettingsA :: Int -> Settings 'A SettingsB :: String -> Settings 'B deriving instance Show (Settings mode) -- | Which setting (A or B) I make should depend -- on whether I choose A or B at compile-time. makeSettings :: Settings mode -> IO (Settings mode) makeSettings template = do let x = case template of SettingsA _ -> SettingsA 123 SettingsB _ -> SettingsB "456" return x main :: IO () main = do setA <- makeSettings (SettingsA undefined) setB <- makeSettings (SettingsB undefined) print setA print setB putStrLn "done."