Haskell 中是否可以通过函数进行模式匹配?

Is it possible to pattern match by function in Haskell?

例如我在haskell中有一个函数:

foo :: Int a => (a -> a -> b) -> a -> b

我想通过第一个参数进行模式匹配:

foo (+) a = a + a

foo (-) a = a - a

但是,此代码会导致编译器错误。 我尝试使用警卫,但也无济于事。 是否可以实现这样的模式匹配?

Is it possible to pattern match by function in Haskell?

Rice's theorem [wiki] 的后果之一是无法确定两个函数是否等价。因此,这意味着可以构造一个可以将两个数字相加的函数,但编译器不可能证明该函数等价于 (+).

如果我们使用引用相等性,那么 \x y -> x + y 不应该与模式匹配,而直接传递 (+) 会匹配。这将是相当奇怪的。假设您有一个函数 f 0 = abs,或 f 0 x = abs x。一个函数的(小)实现细节可以决定另一个函数的行为,这将是非常奇怪的。

函数定义是正确的(在 GHC 9.0.1 和 8.6.5 上测试过)。但是,它不会检查函数是否为 (+):您定义了一个名为 (+) 的变量,您可以在函数体中使用该变量。您可以将它用作中缀运算符,如 x + y(+) x y。但函数定义等同于:

foo :: (a -> a -> b) -> a -> a -> b
foo g x y = g x y

foo :: (a -> a -> b) -> a -> a -> b
foo g x y = x `g` y

如果您打开 -Wname-shadowing 警告,它会发出警告,提示您有一个临时变量与上述上下文中的变量冲突:

ghci> f (+) x y = x + y

<interactive>:1:3: warning: [-Wname-shadowing]
    This binding for ‘+’ shadows the existing binding
      imported from ‘Prelude’ (and originally defined in ‘GHC.Num’)

你的函数的签名可能会导致那么多错误,这里的签名应该是:

f :: (a -> b -> c) -> a -> b -> c
f (+) x y = x + y

但同样,这 不会 与 Prelude 中定义的 (+) 函数匹配。

如果你需要一些参数来确定一个函数,你可以 - 如 - 创建一个代表某些函数的类型,例如:

data <strong>FunctionSelector</strong> = Add | Sub

foo :: Num a => <strong>FunctionSelector</strong> -> a -> a -> a
foo <strong>Add</strong> = (+)
foo <strong>Sub</strong> = (-)