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> = (-)
例如我在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> = (-)