我试图理解Heinrich Apfelmus的文章The Operational Monad Tutorial,他在其中经常使用GADTs。作为一项智力活动,我试图重写他的代码示例,以使他们不再使用GADT。我做不到,现在我可以确定这是因为我的技能有限,还是存在根本问题。
在r/haskell上,爱德华·克梅特(Edward Kmett)说:“如果您具有Rank N类型,则可以始终通过类将GADT转换为最终的[sic]无标签表示形式。”
但是,如果我也不想使用Rank N类型怎么办?我想,我必须牺牲一些东西,但是我仍然应该能够做到。
因此,如果我愿意牺牲某种类型的安全性,请使用幻像类型,类型类等,然后可以在不使用LANGUAGE
扩展名的情况下为类似下面的表达式(有点)编写一个eval函数吗?
-- 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
最佳答案
如果没有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
关于haskell - 是否按照标准Haskell重写GADT代码?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51808983/