gpt4 book ai didi

Haskell 类型家族,理解错误信息

转载 作者:行者123 更新时间:2023-12-04 20:17:28 25 4
gpt4 key购买 nike

在尝试使用 Data.Has 时,我一直在编写如下代码:

data Name = Name; type instance TypeOf Name = Text
type NameRecord = FieldOf Name;

我发现:
instance I NameRecord where
...

抛出编译错误,即:

Illegal type synonym family application in instance



然而:
instance (NameRecord ~ a) => I a where
...

编译得很好。

我相信该错误与 this 有关GHC 中的票,标记为无效。

对票的回应说:

I am not sure what you are suggesting. We cannot automatically transform

instance C (Fam Int) -- (1)

into

instance (Fam Int ~ famint) => C famint -- (2)

This works if there is only one instance, but as soon as there are two such instances, they always overlap.

Maybe you are suggesting that we should do it anyway and programmers should just take the implicit transformation into account. I don't think that this is a good idea. It's confusing for very little benefit (as you can always write the transformed instance yourself with little effort).



有人可以详细说明这个解释,也许有一些示例代码,其中 (1) 失败但 (2) 没有,为什么?

最佳答案

(1)失败但(2)没有的情况是微不足道的;因为类型同义词( type ExampleOfATypeSynonym = ... )在实例声明中是不允许的,但它们在约束中是允许的,任何情况下只有 像这样的例子:

-- (1)
class Foo a
type Bla = ()
instance Foo Bla

... 可以转化为:
-- (2)
class Foo a
type Bla = ()
instance (a ~ Bla) => Foo a

(1) 失败的唯一原因是实例声明中不允许使用类型同义词,这是因为类型同义词类似于类型函数:它们提供从类型名称到类型名称的单向映射,因此如果您有 type B = A和一个 instance Foo B ,不明显的是 Foo A 的实例而是创建。规则存在,所以你必须写 instance Foo A而是明确表示这是实际获取实例的类型。

在这种情况下,类型系列的使用无关紧要,因为问题在于您使用的是类型同义词, NameRecord类型。您还必须记住,如果类型同义词被删除并替换为 FieldOf Name直接编译还是会失败;那是因为“类型族”只是类型同义词的增强版本,所以 FieldOf Name也是 Name :> Text 的“类型同义词”在这种情况下。您必须使用数据系列和数据实例来获得“双向”关联。

有关数据系列的更多信息可以在 GHC documentation 中找到。 .

我想你的意思是“......(2)失败但(1)没有......”

假设我们有一个这样的类型类:
class Foo a where
foo :: a

现在,您可以像这样编写实例:
 instance Foo Int where
foo = 0

instance Foo Float where
foo = 0

main :: IO ()
main = print (foo :: Float)

这正如人们所期望的那样工作。但是,如果将代码转换为:
{-# LANGUAGE FlexibleInstances, TypeFamilies #-}
class Foo a where
foo :: a

instance (a ~ Int) => Foo a where
foo = 0

instance (a ~ Float) => Foo a where
foo = 0

main :: IO ()
main = print (foo :: Float)

它不编译;它显示错误:
test.hs:5:10:
Duplicate instance declarations:
instance a ~ Int => Foo a -- Defined at test.hs:5:10-27
instance a ~ Float => Foo a -- Defined at test.hs:8:10-29

所以,这就是您希望寻找的示例。现在,这只会发生在有多个 Foo 的实例时。使用这个技巧。这是为什么?

GHC解析类型类时,只看实例声明头;即它忽略 => 之前的所有内容.当它选择了一个实例时,它“提交”给它,并检查 => 之前的约束。看看它们是否真实。因此,首先它会看到两个实例:
instance Foo a where ...
instance Foo a where ...

仅根据这些信息显然不可能决定使用哪个实例。

关于Haskell 类型家族,理解错误信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10478329/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com