I'm trying to extend the classic GADTs example around eval-ing a Value, but I'm hitting something I don't fully understand.
data Command a where
Base64_ :: Command a
Take_ :: Int -> Command a
-- eval only works with this definition
-- with this uncommented, cmd breaks with:
--
-- Could not deduce: v ~ T.Text
-- from the context: a ~ T.Text
-- bound by a pattern with constructor:
-- VString :: T.Text -> Value T.Text,
-- in an equation for ‘cmd’
-- ‘v’ is a rigid type variable bound by
-- the type signature for:
-- cmd :: forall c a v. Command c -> Value a -> Value v
data Value v where
VString :: T.Text -> Value T.Text
VInt :: Int -> Value Int
VBool :: Bool -> Value Bool
VNot :: Value Bool -> Value Bool
-- cmd only works with this definition
-- with this uncommented, eval breaks with:
--
-- Couldn't match expected type ‘a’ with actual type ‘T.Text’
-- ‘a’ is a rigid type variable bound by
-- the type signature for:
-- eval :: forall a. Value a -> a
-- data Value v where
-- VString :: T.Text -> Value v
-- VInt :: Int -> Value v
-- VBool :: Bool -> Value v
-- VNot :: Value Bool -> Value v
eval :: Value a -> a
eval (VString i) = i
eval (VInt i) = i
eval (VBool b) = b
eval (VNot b) = not $ eval b
cmd :: Command c -> Value a -> Value v
cmd Base64_ (VString s) = VString $ encodeBase64 s
cmd (_) (_) = VInt 3 -- or show error for no match.
Is what I'm trying to do possible? Is there a single GADT definition that would work with both eval and cmd, or am I getting one of the function signatures incorrect?