【发布时间】:2021-12-15 20:58:06
【问题描述】:
假设我在 Haskell 中有一个简单的数据类型来存储一个值:
data V a = V a
我想让 V 成为 Show 的实例,而不管 a 的类型。如果 a 是 Show 的实例,则 show (V a) 应返回 show a 否则应返回错误消息。或者在 Pseudo-Haskell 中:
instance Show (V a) where
show (V a) = if a instanceof Show
then show a
else "Some Error."
如何在 Haskell 中实现这种行为?
【问题讨论】:
-
Haskell 是一种完全类型擦除的语言;在运行时,内存分配的结构不包含可用于恢复其类型或这些类型实现的类的标记。因此,没有像 Java 或类似语言提供的
instanceof运算符。 (在某些情况下,还有一些更高级的技术可以用于类似的运行时类型反射,但如果你是初学者,你应该首先坚持基础!) -
这种行为无法实现,因为从哲学上讲,每个类型都在每个类中。当然,如果编译器无法find您尝试
show的某种类型的Show实例,则会出现错误;但这在概念上被理解为“你忘记编写必要的实例”而不是“你试图显示一个不可显示的类型”。类型类是开放的,任何人以后都可以为某些库类定义实例。编译器在编译库时不可能证明这不会发生! -
也就是说:这种行为可以用overlapping instances 来模拟,这被认为有点丑陋(甚至不安全)的黑客行为。也许更符合这个想法的是closed type families,尽管它们不允许您实现该显示实例。
-
你通过写
instance Show a => Show (V a) where ...来实现这个行为。那么“Some Error”就变成了编译时类型错误。 -
一些与@leftaroundabout的评论相关的链接okmij.org/ftp/Haskell/typeEQ.htmlwiki.haskell.org/GHC/AdvancedOverlap
标签: haskell