Haskell 中的“模式匹配”类型

Zhi*_*gor 1 haskell types functional-programming

我想要一个函数f作为Ints的增量和所有其他类型的标识。我尝试启用TypeApplications扩展并以最直接的方式执行此操作:

f :: forall a. a -> a
f @Int x = x + 1
f @_   x = x
Run Code Online (Sandbox Code Playgroud)

但是扩展并没有启用这样的模式:

<interactive>:6:1: error: Parse error in pattern: f @Int
Run Code Online (Sandbox Code Playgroud)

Haskell 中是否有类型(或类似机制)的模式匹配?

chi*_*chi 8

如前所述,这在 Haskell 中是不可能实现的,因为它会违反称为“参数性”的参数多态性的基本属性之一,它确保任何多态函数满足称为“自由定理”的特定属性。

特别是,类型的终止函数forall a. a -> a必须是身份。没有其他可能的实现。

话虽如此,如果我们允许对 type 进行约束a,这将成为可能。通常,运行时类型测试是通过Typeable类型类在 Haskell 中完成的:

f :: forall a. Typeable a => a -> a
f x = case eqT @a @Int of    -- Is a ~ Int ?
   Just Refl -> x + 1        -- If it is, we can add one.
   Nothing   -> x            -- Otherwise, return x as-is.
Run Code Online (Sandbox Code Playgroud)

这需要一堆 GHC 扩展,并导入Data.Typeable.


Dan*_*ner 8

有,但你不能像在计算级别那样有一个贯穿模式。也就是说,在计算层面,我可以写

f 0 = 42
f n = n-1
Run Code Online (Sandbox Code Playgroud)

一起一落,通过模式n的作品正是当没有其他模式的匹配。在类型级别,您不能这样做——甚至嵌套在其他模式中。你可以有一个匹配任何东西的模式,但不能匹配“其他任何东西”——如果你匹配任何东西,你就不能有任何其他模式。

因此,一旦您拥有要与之匹配的模式集合,就可以编写类型类和实例。所以,如果你想支持IntBool和列表,你可以写:

class F a where f :: a -> a
instance F Int where f = succ
instance F Bool where f = id
instance F [a] where f = id
Run Code Online (Sandbox Code Playgroud)

最后一个例子展示了我之前的意思,你可以有一个匹配任何东西的模式,但不能匹配“其他任何东西”的模式:[a]是一个很好的实例,但它排除了以后创建[Bool]实例的可能性。