Haskell中具有类型的冒险:GADT:为什么进行以下类型检查?

达米安·纳达莱斯(Damian Nadales)

我下面这个讲座由西蒙·佩顿-琼斯GADT的。在那里,声明了以下数据类型:

data T a where
  T0 :: Bool -> T Bool
  T1 :: T a

然后要问的问题是以下函数的类型是什么:

f x y = case x of
          T0 _ -> True
          T1   -> y

在我看来,唯一可能的类型是:

f :: T a -> Bool -> Bool

但是,以下类型:

f :: T a -> a -> a

也有效!实际上,您可以使用f以下方法:

 f (T1) "hello"

我的问题是为什么第二类签名f有效?

开支

通常,要输入检查

case e of
  K1 ... -> e1
  K2 ... -> e2
  ...

要求所有表达式ei共享一个公共类型。

使用GADT时,情况仍然如此,除了构造函数在每个分支中提供了一些T ~ T'已知在该分支中保存的类型相等方程因此,当检查所有的人ei共享一个共同的类型时,我们不再要求它们的类型相同,而仅当类型方程式成立时才要求它们相等。

尤其是:

f :: T a -> a -> a
f x y = -- we know x :: T a , y :: a
   case x of
      T0 _ -> -- provides a ~ Bool
              True   -- has type Bool
      T1   -> -- provides a ~ a (useless)
              y      -- has type a

在这里,我们需要检查Bool ~ a一般情况下哪个是假的,但在这里变为真,因为我们只需要在提供的equals下检查即可a ~ Bool而且,在这种情况下,它成为事实!

(说实话,类型系统所做的事情略有不同,而是检查两个分支是否都等于签名中声明的类型(在已知的相等性下),但是让我保持简单。对于GADT模式匹配,这种签名是总是需要某种形式的。)

请注意,这就是GADT的重点-它们允许类型检查其分支显然涉及不同类型的模式匹配。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么在此GADT上进行模式匹配似乎会在类型检查器中引入歧义?

为什么 std::function 没有进行类型检查?

在Haskell中,为什么“ fmap(重复3)Just”具有类型“ a-> [Maybe a]”

GADT:为什么没有选择最弱或最强类型?

Scala-为什么使用具有两个泛型参数的超类型会导致Scala类型检查器对子类型进行不同的处理?

为什么要进行类型检查?

为什么Haskell中没有`Cofunctor`类型类?

为什么在GHC 7.10中进行类型检查的代码不再在GHC 8.0.1中进行类型检查?

在 Haskell GADT 中创建递归类型

为什么在此示例中参数b具有类型a?

在Haskell中,如何根据GADT将无类型的AST解析为有类型的AST?

为什么Idris的Refl有时不进行类型检查?

为什么 Java 不能对这段代码进行类型检查?

为什么此功能无法进行类型检查?

为什么不进行这种简单的Morte程序类型检查?

为什么此TypeScript代码无法进行类型检查?

为什么在Idris中不进行涉及“ mod”的相等性类型检查?

为什么不对initializer_list中的值进行类型检查?

具有参数类型的Haskell类型类

为什么在实现具有关联类型的关联const时,Rust为什么要对Self进行大小调整?

为什么通道类型中带有“ <-”?

在Haskell中,为什么会有类型类层次结构/继承?

为什么Haskell基本库中没有“非空列表”类型?

为什么在Haskell中没有函子上的等分词的类型类?

为什么只有val类型的对象在kotlin中具有组件功能?

为什么Haskell中会有“数据”和“新类型”?

如何区分具有不同幻像类型的GADT构造函数?

GADT确实具有代表性的类型角色吗

在Haskell中使用RankNTypes进行类型检查