{-# LANGUAGE KindSignatures #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE DataKinds #-} data OutputTag = A | B | C data Input (o :: OutputTag) where I1 :: Int -> Input A I2 :: String -> Input B data Output (o :: OutputTag) where OA :: String -> Output A OB :: Bool -> Output B OC :: Output C inputToOutput :: (tag ~ tag') => Input tag -> Output tag' inputToOutput (I1 0) = OC inputToOutput (I1 i) = OA (show i) inputToOutput (I2 s) = OB (s == "x") main :: IO () main = let OA s = inputToOutput (I1 4) in print s