【问题标题】:Why don't existential types have pattern matching?为什么存在类型没有模式匹配?
【发布时间】:2017-07-21 22:37:15
【问题描述】:

即使没有扩展 ExistentialQuantification,Haskell 也支持一些存在类型,通过类型同构,任何类型类 C

(forall a. C a => (a -> b))  ~  ((exists a. C a => a) -> b)

所以函数f :: C a => a -> b 需要一个x 类型的exists a. C a 参数。但是 Haskell 不允许将 x 与某些类型的 C 进行模式匹配(以狂野匹配 _ 结束,因为类型类通常是无限的)。

这很奇怪,因为存在类型是广义求和类型。 Haskell 确实支持带有 data 关键字的有限和类型,并允许对它们进行模式匹配。在 C++、Java 和 C# 等语言中,存在类型是接口,它们支持使用 dynamic_castinstanceof 等关键字进行模式匹配。

Haskell 没有为上面的f 等函数实现模式匹配有什么原因吗?

【问题讨论】:

  • 如果我理解正确,您希望对类型进行模式匹配。这是不可能的,因为没有运行时类型信息。对于普通的 sum 类型,有关已使用的构造函数的信息会在运行时保留。对于存在主义者来说,什么都没有。如果你想要这样的东西,你可以使用 GADT 作为见证,或者使用Typeable
  • @kosmikus 是的,我想对类型进行模式匹配。我知道 GHC 的实施方式是不可能的,我在问为什么 GHC 是这样实施的。您能否举一个使用 GADT 进行模式匹配的无限总和类型的示例?我不清楚该怎么做。
  • 为什么要以其他方式实施 GHC?类型上的模式匹配只会导致不好的做法;可用类型的集合是无限的,如果没有包罗万象的案例,您永远无法真正获得全面覆盖;并且在运行时获取类型信息通常会带来很大的性能开销。
  • iso不应该是(forall a. (C a => a) -> b) ~ ((exists a. C a => a) -> b)吗?

标签: haskell


【解决方案1】:

Haskell 被设计为允许类型擦除实现。我们仍然可以在运行时不携带所有类型级别信息的情况下运行 Haskell。这允许实现减少内存占用。

请注意,程序员仍然可以通过添加Typeable a 约束来选择在运行时保留类型信息。然后cast 可用于对类型进行模式匹配。

此外,无法在运行时对类型执行模式匹配对于保证parametricity / free theorems 很重要。例如,如果我们有一个多态函数

f :: forall a. a -> a

我们保证f 是身份(或无法终止)。这是因为任何这样的f 都必须是自然转换,除了身份之外没有其他选项可用。如果我们可以写,那就不是真的了

f x = if a==Int then x+1 else x

如果我们添加Typeable a,确实可以写出类似的东西。

同样,g :: a->a->a 必须是投影,h :: [a]->[a] 不能将[True] 发送到[False,True]。此外,如果h [1,2]=[2,2,1] 则必然h "ab" = "bba"。自然而然,这些函数必须在所有类型a 上“统一”工作。

【讨论】:

    【解决方案2】:

    如果你想对类型进行模式匹配,那是不可能的,因为

    1. 要匹配的类型有无数种,因此您的模式永远不会详尽。

    2. 作为一个实现细节,GHC 在编译时会擦除所有类型信息,因此无论如何都无法实现。 (这可能是由于第 1 点。)

    您提到 OO 语言通常有类似 instanceof 运算符的东西。您可以在 Haskell 中使用 Typeable 类来执行此操作。如果一个类型是Typeable 的实例,您可以使用toDyn 将其“转换”为Dynamic 类型。然后您可以稍后尝试使用fromDynamic 将其转换回,这将返回Maybe。 (或fromDyn,它返回一个默认值。)所以Dynamic 类型类似于Java 的Object;它可以是任何东西。通常这并没有足够的限制,而且通常你不会在 Haskell 中看到这种编程。

    您还可以使用 GADT 来表示 有限 组类型,然后您可以对其进行模式匹配。或者常规数据结构,就此而言。

    【讨论】:

    • 如果模式以匹配 _ 结尾,则它们是详尽的。根据 Curry-Howard,exists x. C x 类型在逻辑上对应于存在量化,其中C 成为谓词。然后 x 在类型 D 上的模式匹配对应于排中定律,在数学推理中经常使用:x 具有属性 D 或者没有。严格来说,DC 的类型子类,但单一类型将是一个好的开始。
    • @V.Semeria “那么类型 D 上的 x 模式匹配对应于排中律,在数学推理中经常使用” - 你已经一针见血了。尝试编写forall a . Either a (Not a) 类型的函数(提示——你不能)。排中定律不适用于构造数学,即直觉类型系统(逻辑)。如果这让您不快,抱歉,您只是在寻找不同的逻辑(编程语言),而不是 Haskell。
    • @user2407038 确实!现在我记得读到库里-霍华德的逻辑必须是直觉的。当时我认为这实际上并不重要,不久之后就忘记了。顺便问一下Not a 的类型是什么? a -> bottom ?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    • 2019-11-15
    相关资源
    最近更新 更多