用标准Haskell重写GADT代码?

Mar*_*urg 2 haskell gadt

我试图理解Heinrich Apfelmus 的文章操作Monad教程,他在那里使用GADTs很多.作为一项心理练习,我试图重写他的代码示例,以便他们不再使用GADT.我不能这样做,现在我知道这是因为我的技能有限,还是存在根本问题.

r/haskell上, Edward Kmett说" 如果你有Rank N类型,你总是可以通过一个类将GADT转换为最终[sic]无标记表示. "

但是,如果我不想使用Rank N类型呢?我想,我必须牺牲一些东西,但我仍然能够做到.

所以,如果我愿意牺牲一些类型的安全性,使用幻像类型,类型类和诸如此类,那么我可以为表达式(有点)编写一个eval函数,如下所示,而不使用LANGUAGE扩展吗?

                           -- using GADTs :
data Expr = I Int  |       -- Int  -> Expr Int
            B Bool |       -- Bool -> Expr Bool
            Add Expr Expr  -- Expr Int -> Expr Int -> Expr Int
            Eq  Expr Expr  -- Expr 1   -> Expr a   -> Expr Bool
Run Code Online (Sandbox Code Playgroud)

And*_*ács 7

如果没有GADT,你不知道是否Expr是好类型的,所以你只能实现一个eval可能抛出错误的东西.

eval :: Expr -> Maybe (Either Int Bool)
eval (I n) = pure (Left n)
eval (B b) = pure (Right b)
eval (Add e1 e2) = do
  x1 <- eval e1
  x2 <- eval e2
  case (x1, x2) of
    (Left n1, Left n2) -> pure (Left (n1 + n2))
    _                  -> Nothing
eval (Eq e1 e2) = do
  x1 <- eval e1
  x2 <- eval e2
  case (x1, x2) of
    (Left  n1, Left n2)  -> pure (Right (n1 == n2))
    (Right b1, Right b2) -> pure (Right (b1 == b2))
    _                    -> Nothing
Run Code Online (Sandbox Code Playgroud)


chi*_*chi 5

如果没有GADT,我们需要一个Value总和类型,包含所有可能的结果.我们还需要使我们的评估函数部分或返回类似的东西Maybe Value.

data Value = VI Int | VB Bool

eval :: Expr -> Value
eval (I i) = VI i
eval (B b) = VB b
eval (Add e1 e2) = case (eval e1, eval e2) of
   (VI i1, VI i2) -> VI (i1+i2)
   _              -> error "runtime type error"
...
Run Code Online (Sandbox Code Playgroud)