没有方法的类型类,用作约束:它们是否得到字典?

问题描述 投票:4回答:1

如果我使用类型类来重载方法,那就是在'字典传递样式'中实现的。也就是说,该方法获得一个额外的参数(不会出现在表面Haskell中);要解决重载方法,请按照“正确”参数的类型查找字典;并从字典中提取方法实现。 As described in this q, for example

但是没有方法的类型怎么办?它们可以用作约束。他们有字典吗?它包含什么?

对于一个具体的例子:

module M  where

class C a             -- no methods
                      -- no instances in module M
f :: C a => a -> Bool
f x = blah

在这个模块中没有C的实例,所以如果将M导入其他模块(使用C实例),f的字典查找是如何编码的?

通常的情况是,班级C有方法;有关f等式的RHS要求他们;所以想要的C a被编码为方法调用的字典查找。

补充问题:(如果有人还在听)

2A。对于具有超类约束的无方法类型类:约束在字典中的位置是什么? comment on a ticket from SPJ似乎暗示它是字典数据构造函数的参数。

2B。对于带有约束的无方法类型类实例:再次将约束放在字典中的哪个位置?

动机

@Daniel在评论中询问这些q的动机。除了理解编译器内部更好一点......

GHC将表面Haskell转换为内部表示:系统FC,在每个函数应用程序中都有明确的类型签名。 (这些应用程序必须包括应用于类的字典。)我试图理解类和实例的所有类型相关组件在字典中的位置;弄清楚FC中的术语如何获得与原始Haskell的等效表示。然后我不明白[没有方法的类型]如何适应。因为这些类不能直接作为表面Haskell中的术语出现,而只是作为约束。那么对于这样一个在术语水平上代表它的类来说,它必须是dictionar(ies)。

如果你想问这是怎么回事:FC似乎有一个限制,它不能代表功能依赖。与无法生成类型级证据有关的事情。然后我想了解这种限制是如何产生的/ FunDeps不能(或目前没有)代表什么?

haskell typeclass
1个回答
7
投票

[没有方法的类型]是否有字典?它包含什么?

是的,有一个没有字段的字典。

相比:

class Monoid a where
    mempty :: a
    mappend :: a -> a -> a
data DictMonoid a = DictMonoid a (a -> a -> a)

class C a
data DictC a = DictC

如果将M导入其他模块(使用C实例),f的字典查找是如何编码的?

类型推断用于确定调用f时需要的实例;然后GHC在其已知实例(=已知词典)的集合中查找该类型。

这个过程的一个可能结果是我们确定需要的实例是多态的,并且没有完全多态的实例。然后将适当的约束(例如C aC m或其他)附加到调用f的任何术语的推断类型 - 然后将其编译为函数,该函数代表f接受字典并将其传递。

对于具有超类约束的无方法类型类:约束在字典中的位置是什么?

某处。你可以用表面语言来区分不同的地方。例如,考虑:

class Semigroup a => Monoid a where mempty :: a
data DictMonoid1 a = DictMonoid1 (DictSemigroup a) a
data DictMonoid2 a = DictMonoid2 a (DictSemigroup a)

这些是在超级类词典的位置上可以做出的两种选择。但它可能有什么不同呢?

好的,但是你问过无方法类型类。但答案是一样的。您不能告诉超级类字典存储的顺序。

class (A a, B a) => C a
data DictC1 a = DictC1 (DictA a) (DictB a)
data DictC2 a = DictC2 (DictB a) (DictA a)

您可以做些什么来区分它们之间的区别?没有。

对于带有约束的无方法类型类实例:再次将约束放在字典中的哪个位置?

无处。它们成为调用者必须提供的用于接收字典的参数。当然,所提供的字典的特定字段可以由新字典封闭。例:

class Ord a where compare :: a -> a -> Ordering
data DictOrd a where DictOrd (a -> a -> Ordering)

instance (Ord a, Ord b) => Ord (a, b) where
    compare (a,b) (a',b') = compare a a' <> compare b b'
instanceOrdTuple :: DictOrd a -> DictOrd b -> DictOrd (a,b)
instanceOrdTuple (DictOrd comparea) (DictOrd compareb)
    = DictOrd $ \(a,b) (a',b') -> comparea a a' <> compareb b b'

好的,但是你问过无方法类型类。但答案并没有太大的不同。实例的约束字典不会存储在任何地方,就像之前一样;唯一的区别是,现在我们也可以确定即使是提供的词典的字段也没有被关闭。

class A a where whateverA :: a -> Int
class B a where whateverB :: Int -> a
class C a
data DictA a = DictA (a -> Int)
data DictB a = DictB (Int -> a)
data DictC a = DictC

instance (A a, B a) => C [a]
instanceCList :: DictA a -> DictB a -> DictC [a]
instanceCList (DictA whateverAa) (DictB whateverBa) = DictC

以下评论回复了旧版本的问题。

在这个模块中没有C的实例,因此编译器无法释放fs约束。

它不需要。 f被编译成一个以字典为参数的函数;没有必要创建一个字典来编译f,只是为了编译它的调用者。

编译器无法释放由C Char方程引起的y约束。它有什么作用?

它报告它无法释放C Char约束并退出失败。 (这甚至不能作为一个问题 - 只需尝试一下,亲眼看看!)

© www.soinside.com 2019 - 2024. All rights reserved.