我第一次尝试使用GADT,我想实现变量替换。当然,如果类型相同,我只能进行替换。据我了解,这应该可以使用:〜:from Data.Type.Equality。但不知何故,编译器不希望我使用:〜:根本。为了试一试,我编写了以下愚蠢的函数。
lol :: Int -> Int -> Bool
lol a b = case a :~: b of
Refl -> True
_ -> False
编译器告诉我:
Not in scope: data constructor ‘:~:’
我尝试了以下事项:
在尝试了我想到的所有事情并在情绪崩溃前不久,我决定在这里提出问题。有人知道我的问题是什么吗?您可能需要其他信息来诊断它,所以请告诉我我能提供的任何信息。由于它是一个相当大的项目,我不认为提供整个源代码是有用的......
好吧,似乎我完全误解了这种方式:〜:有效。所以我把这个问题完全改写为我真正需要的东西:
-- a is a variable symbol used for variable substitution.
-- b is a function symbol used for function substitution.
-- c represents a type of value that is contained.
data Ast a b c where
BoolConst :: Bool -> Ast a b Bool
IntConst :: Int -> Ast a b Int
Var :: Eq a => a -> c -> Ast a b c
-- Function application for a function with symbol b.
App :: (Eq b, Eq c) => b -> Ast a b c -> Ast a b Int
UnOp :: UnaryOperator c d -> Ast a b c -> Ast a b d
BinOp :: BinaryOperator c d e -> Ast a b c -> Ast a b d -> Ast a b e
NaryOp :: NaryOperator c -> [Ast a b c] -> Ast a b c
Ite :: Ast a b Bool -> Ast a b c -> Ast a b c -> Ast a b c
我省略了运算符的定义,但你可以想象。首先:据我了解,不可能实现具有多个参数的函数。因此,我将App实现为仅使用一个参数而不是列表,并通过以某种方式重复应用来模拟多个参数。我仍然需要进行一些更改才能使其工作,但这不是问题所在。
现在我想编写两个替换变量和函数的substituteVar
和substituteFunc
函数。为简单起见,我们暂时关注substituteVar
。我想使用以下签名:
substituteVar :: Eq a => M.Map a (Ast a b c) -> Ast a b d -> Ast a b d
类型参数c
和d
基本上用作返回类型。但我不知道如何处理Haskell不“知道”替换c
的类型是否与遇到的变量d
的类型相同的问题。所以我认为我可以以某种方式使用:~:
,但我想我错了。顺便说一句,我目前只需要Bool和Int类型,但我希望它可以扩展到更多(但仍然是一个小数字)。
我知道为名为BoolVar
和IntVar
的变量使用两个构造函数的可能性。虽然这有点难看,但有点适用于变量,即使我将它扩展到5种类型,它也会变得非常混乱。我基本上需要一个类型构造函数的每个参数和返回类型的组合。因此,我认为这个解决方案不会扩展,不知何故感觉应该有更容易的可能性。
答案 0 :(得分:2)
好的,这是迄今为止我在Stackoverflow上最愚蠢的问题。我想删除它,但也许有一天有人搜索同样的问题并很高兴看到答案,因此我会回答它。
我完全误解了:〜:运算符。它适用于类型而不是术语,因此我的例子毫无意义。
我没有答案,但我不再需要了。我喜欢GADT的想法,但我试图将它应用到它们非常难以使用的地方。可能更有经验的Haskell程序员可以在我的上下文中正确使用它们,但我绝不是一个好的Haskell程序员。因此,我将使用普通的ADT并放弃某种类型的安全性,即编译器不会禁止使用布尔等产品。但作为交换,我实际上可以使它工作。
此外,完全改变我的问题是一种非常糟糕的风格。小的适应性是可以的,但如果方向完全改变,我应该创建一个具有适当标题的单独问题。目前的状态让每个登陆此页面的人都感到困惑。此外,作为一个具有适当标题的单独问题,我会有更好的机会获得一个好的答案。