如果我使用类型类重载方法,则以“字典传递样式”实现。也就是说,该方法有一个额外的参数(在表面Haskell中不会出现)。为了解决重载,该方法通过其“适当”参数的类型查找字典;并从字典中拉出方法实现。如此q中所述。
但是没有方法的类型类呢?它们可以用作约束。他们有字典吗?它包含什么?
对于一个特定的例子:
module M where
class C a -- no methods
-- no instances in module M
f :: C a => a -> Bool
f x = blah
Run Code Online (Sandbox Code Playgroud)
C该模块中没有适用的实例,因此,如果M将其导入到其他模块(带有C实例)中,则如何f对字典查找进行编码?
通常的情况是该类C具有方法。有人呼吁他们方程的RHS f;因此通缉将C a被编码为方法调用的字典查找。
补充q :(如果有人还在听)
2a。对于具有超类约束的无方法类型类:约束在字典中的位置在哪里?SPJ对票证的评论似乎表明这是字典数据构造函数的一个参数。
2b。对于带有约束的无方法类型类实例:约束再次在字典中的什么位置?
动机
@Daniel在评论中问这些q的动机。除了仅了解编译器内部知识外,还可以...
GHC将表面Haskell转换为内部表示形式:System F C,该系统在每个函数应用程序中都具有明显的类型签名。(这些应用程序必须包括对类的字典进行申请。)我试图了解类和实例decl的所有与类型相关的组件在字典中的位置。找出F C中的术语如何与原始Haskell等效。然后,我不理解[没有方法的类型类]如何适合。因为这些类不能直接作为表面Haskell中的术语出现,而只能作为约束出现。然后,对于此类在术语级别代表其的类,它必须是字典。
如果您想问这是怎么回事:F C中似乎存在一个局限性,即它不能表示功能依赖关系。与无法生成类型级别的证据有关。然后,我想了解这种限制是如何产生的/关于FunDeps不能(或目前没有)代表什么?
有没有[没有方法的类型类]的字典吗?它包含什么?
是的,有一本没有字段的字典。
比较:
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
Run Code Online (Sandbox Code Playgroud)
如果
M导入到其他模块(带有C实例)中,则f字典查找如何编码?
类型推断用于确定何时f调用哪个实例;然后GHC在其已知实例(=已知词典)集合中查找该类型。
此过程的一个可能结果是,我们确定需要的实例是多态的,并且没有完全多态的实例。然后,将适当的约束(例如C a或C 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)
Run Code Online (Sandbox Code Playgroud)
这些是将超类的字典放在何处的仅有的两种选择。但是它可能会产生什么变化?
好的,但是您询问了无方法类型类。但是答案是一样的。您无法说出超类词典的存储顺序。
class (A a, B a) => C a
data DictC1 a = DictC1 (DictA a) (DictB a)
data DictC2 a = DictC2 (DictB a) (DictA a)
Run Code Online (Sandbox Code Playgroud)
您可能怎么做才能分辨出两者之间的区别?没有。
对于带有约束的无方法类型类实例:约束再次在字典中的什么位置?
无处。它们成为调用者必须提供以接收字典的参数。当然,提供的字典的特定字段可能会被新字典关闭。例:
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'
Run Code Online (Sandbox Code Playgroud)
好的,但是您询问了无方法类型类。但是答案并没有太大的不同。实例的约束字典没有像以前一样存储在任何地方;唯一的区别是,现在我们还可以确保即使提供的词典的字段都没有关闭。
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
Run Code Online (Sandbox Code Playgroud)
以下评论回复了该问题的旧版本。
C该模块中没有适用的实例,因此编译器无法释放fs约束。
不需要。f被编译为以字典为参数的函数;无需创建要编译的字典f,仅需编译其调用者即可。
编译器无法释放
C Char的方程式引起的约束y。它有什么作用?
它报告说它无法解除C Char约束并且退出失败。(这甚至不算是一个问题,只需尝试一下,自己看看吧!)
| 归档时间: |
|
| 查看次数: |
190 次 |
| 最近记录: |