在 let 绑定中排名 N 类型

Rank N types in let bindings

所以我已经做到了...

{-# LANGUAGE Rank2Types, GADTs  #-}

type Record fields = forall t. fields t -> t

data PersonField t where
    Name :: PersonField String
    Age :: PersonField Int
type Person = Record PersonField

然后这个...

nigel :: Person
nigel Name = "Nigel"
nigel Age = 39

一切似乎都按预期进行。

我正在努力解决的问题是如何在 let 绑定中定义一个 Person 值。例如,这不起作用:

abigail :: Person
abigail = let x Name = "Abigail"
              x Age = 27 
           in x  

给我:

Couldn't match expected type `t1' with actual type `[Char]' `t1' is untouchable ...

有没有办法让这个在 let 绑定中工作?

涉及 GADT 时需要显式类型注释:

abigail :: Person
abigail = let x :: Person
              x Name = "Abigail"
              x Age = 27 
           in x

没有它,GHC大概能看到

let x Name = "Abigail"

并说“好的,x 是一个函数,从 Name 的类型,即 PersonField String"Abigail" 的类型,即 String . 在下一行,

let x Name = "Abigail"
    x Age = 27

GHC 现在发现 x 也接受 PersonField Int 和 return 一个数字。这与之前推断的类型冲突,引发类型错误。

使用显式类型注释,类型推断不会尝试为 x 推断错误的类型:它是由用户提供的。相反,只会执行类型检查。