Haskell Data.Type.Equality“不在范围内:数据构造函数':〜:'”

时间:2015-11-11 20:23:11

标签: haskell

我第一次尝试使用GADT,我想实现变量替换。当然,如果类型相同,我只能进行替换。据我了解,这应该可以使用:〜:from Data.Type.Equality。但不知何故,编译器不希望我使用:〜:根本。为了试一试,我编写了以下愚蠢的函数。

lol :: Int -> Int -> Bool
lol a b = case a :~: b of
  Refl -> True
  _    -> False

编译器告诉我:

Not in scope: data constructor ‘:~:’

我尝试了以下事项:

  • 首先,我想,这在某种程度上是安装了错误版本的问题。我看到:=:用于旧版本。但是:=:也没用。
  • 我将cabal文件中base的版本明确更改为4.8.1.0,仍然没有运气。
  • 我将Data.Type.Equality的整个源代码复制到一个名为TypeEquality的单独文件中并导入它。仍然是相同的错误消息。
  • 我认为这可能与我需要启用的一些扩展有关。我启用了Data.Type.Equality使用的所有扩展,但NoImplicitPrelude除外。仍然没有运气。
  • 我将所有内容复制到我使用它的同一个文件中。仍然是相同的错误消息。
  • 我尝试使用此模块搜索其他人。我找不到任何有用的东西。无论如何,这本来都不错,因为我还不太懂得如何使用它。
  • 我查找了“不在范围内”的其他StackOverflow qustions。我没有浏览所有这些,但似乎它总是与大写/小写问题有关,在我的情况下这似乎不是问题。

在尝试了我想到的所有事情并在情绪崩溃前不久,我决定在这里提出问题。有人知道我的问题是什么吗?您可能需要其他信息来诊断它,所以请告诉我我能提供的任何信息。由于它是一个相当大的项目,我不认为提供整个源代码是有用的......

修改

好吧,似乎我完全误解了这种方式:〜:有效。所以我把这个问题完全改写为我真正需要的东西:

-- 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实现为仅使用一个参数而不是列表,并通过以某种方式重复应用来模拟多个参数。我仍然需要进行一些更改才能使其工作,但这不是问题所在。

现在我想编写两个替换变量和函数的substituteVarsubstituteFunc函数。为简单起见,我们暂时关注substituteVar。我想使用以下签名:

substituteVar :: Eq a => M.Map a (Ast a b c) -> Ast a b d -> Ast a b d

类型参数cd基本上用作返回类型。但我不知道如何处理Haskell不“知道”替换c的类型是否与遇到的变量d的类型相同的问题。所以我认为我可以以某种方式使用:~:,但我想我错了。顺便说一句,我目前只需要Bool和Int类型,但我希望它可以扩展到更多(但仍然是一个小数字)。

我知道为名为BoolVarIntVar的变量使用两个构造函数的可能性。虽然这有点难看,但有点适用于变量,即使我将它扩展到5种类型,它也会变得非常混乱。我基本上需要一个类型构造函数的每个参数和返回类型的组合。因此,我认为这个解决方案不会扩展,不知何故感觉应该有更容易的可能性。

1 个答案:

答案 0 :(得分:2)

好的,这是迄今为止我在Stackoverflow上最愚蠢的问题。我想删除它,但也许有一天有人搜索同样的问题并很高兴看到答案,因此我会回答它。

回答我原来的问题

我完全误解了:〜:运算符。它适用于类型而不是术语,因此我的例子毫无意义。

关于我的第二个问题

我没有答案,但我不再需要了。我喜欢GADT的想法,但我试图将它应用到它们非常难以使用的地方。可能更有经验的Haskell程序员可以在我的上下文中正确使用它们,但我绝不是一个好的Haskell程序员。因此,我将使用普通的ADT并放弃某种类型的安全性,即编译器不会禁止使用布尔等产品。但作为交换,我实际上可以使它工作。

此外,完全改变我的问题是一种非常糟糕的风格。小的适应性是可以的,但如果方向完全改变,我应该创建一个具有适当标题的单独问题。目前的状态让每个登陆此页面的人都感到困惑。此外,作为一个具有适当标题的单独问题,我会有更好的机会获得一个好的答案。