简体   繁体   English

为什么存在性类型没有模式匹配?

[英]Why don't existential types have pattern matching?

Even without extension ExistentialQuantification , Haskell supports some existential types, via the type isomorphism, for any typeclass C , 即使没有扩展ExistentialQuantification ,Haskell也可以通过类型同构支持任何存在于C类的存在性类型,

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

So a function f :: C a => a -> b expects an argument x of type exists a. C a 因此,函数f :: C a => a -> b a- f :: C a => a -> b期望类型exists a. C a x的参数exists a. C a exists a. C a . exists a. C a But Haskell doesn't allow to pattern match x against some types of C (finishing by a wild match _ , because type classes are usually infinite). 但是Haskell不允许将x与某些类型的C进行模式匹配(以通配符_ ,因为类型类通常是无限的)。

This is strange, because existential types are generalized sum types. 这很奇怪,因为存在类型是广义和类型。 Haskell does support finite sum types with the data keyword and allows pattern matching for them. Haskell确实支持data关键字的有限和类型,并允许它们进行模式匹配。 In languages such as C++, Java and C#, existential types are interfaces and they support pattern matching with keywords such as dynamic_cast or instanceof . 在诸如C ++,Java和C#之类的语言中,存在类型是接口,它们支持与诸如dynamic_castinstanceof关键字进行模式匹配。

Is there a reason why Haskell didn't implement pattern matching for functions such as f above ? Haskell不对上述f函数实现模式匹配是有原因的吗?

Haskell was designed so to allow a type-erasing implementation. Haskell被设计为允许类型擦除实现。 We can still run Haskell without carrying all the type-level information at runtime. 我们仍然可以运行Haskell,而无需在运行时携带所有类型级别的信息。 This allows implementations to reduce the memory footprint. 这允许实现减少内存占用。

Note that the programmer can still choose to keep type information around at runtime by adding Typeable a constraints. 请注意,程序员仍然可以选择通过添加Typeable a约束来在运行时保留类型信息。 cast can then be used to pattern match on types. cast然后可以被用于图案匹配上的类型。

Further, the inability of performing pattern matching on types at runtime is important to guarantee parametricity / free theorems . 此外,在运行时无法对类型执行模式匹配对于保证参数/自由定理很重要。 For instance, if we have a polymorphic function 例如,如果我们有一个多态函数

f :: forall a. a -> a

we are guaranteed that f is the identity (or fails to terminate). 我们保证f是身份(或无法终止)。 This is because any such f must be a natural transformation, and no other options but the identity are available. 这是因为任何这样的f必须是自然变换,并且除身份以外没有其他选择可用。 That would not be true if we could write 如果我们可以写那不是真的

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

Something like that can indeed be written if we add Typeable a . 如果我们添加Typeable a ,确实可以写出Typeable a

Similarly, g :: a->a->a must be a projection, and h :: [a]->[a] can not send [True] to [False,True] . 同样, g :: a->a->a必须是一个投影,并且h :: [a]->[a]无法将[True]发送到[False,True] Further, if h [1,2]=[2,2,1] then necessarily h "ab" = "bba" . 此外,如果h [1,2]=[2,2,1]则必定h "ab" = "bba" By naturality, these function must work "uniformly" over all the types a . 自然地,这些函数必须在所有类型a “均匀地”工作。

If you want to pattern match on types, that is impossible, because 如果要对类型进行模式匹配,那是不可能的,因为

  1. There are an infinite number of types to match against, so your patterns can never be exhaustive. 有无数的类型可以匹配,因此您的模式永远不会穷尽。

  2. As an implementation detail, GHC erases all type information at compile-time, so there's no way to implement this anyway. 作为实现细节,GHC在编译时会擦除所有类型信息,因此无论如何都无法实现 (Which is probably due to point #1.) (这可能是由于第一点所致。)

You mention that OO languages typically have something like an instanceof operator. 您提到OO语言通常具有类似于instanceof运算符的功能。 You can do this in Haskell with the Typeable class. 您可以在Haskell中使用Typeable类进行此操作。 If a type is an instance of Typeable , you can "cast" it to the Dynamic type using toDyn . 如果类型是Typeable的实例, Typeable可以使用toDyn将其“投射”为Dynamic类型。 You can then later try to cast it back using fromDynamic , which returns a Maybe . 然后,您可以稍后尝试使用fromDynamic将其投射回去,该方法返回Maybe (Or fromDyn , which returns a default value.) So the Dynamic type is similar to Java's Object ; (或者fromDyn ,它返回一个默认值。)因此Dynamic类型类似于Java的Object it can be anything . 可以是任何东西 Typically that's not really restrictive enough, and generally you tend not to see this kind of programming in Haskell. 通常,这还不够严格,通常,您倾向于在Haskell中看不到这种编程。

You can also use GADTs to represent a finite set of types which you can then pattern match against just fine. 您还可以使用GADT表示一组有限的类型,然后就可以对其进行模式匹配。 Or regular data structures, for that matter. 或常规数据结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM