Haskell: 为什么我不能对函数进行模式匹配?

Haskell: Why can't I pattern match against function?

如:

extract (f x) = x

我想做的是从函数或类型构造函数中提取参数,例如

extract succ 4 = 4
extract Just 4 = 4

ps。 extract (f x) = f 也不行。

函数式编程,尤其是纯函数式编程中的一个关键概念是等式推理。 Haskell 中的 = 是实际相等(抛开模式匹配的顺序等)。所以当我们写

f 3 = 12

这意味着f 312实际上是同一个东西——完全没有区别。由于 extract 12 没有任何意义,因此 extract (f 3).

也没有

从另一个方向来看,在运行时间,无法判断某个值是通过将某个函数应用于某个其他值而形成的。提供此类信息通常非常昂贵,而且通常用处不大。

您绝对可以使用数据构造函数对数据结构进行模式匹配,例如您的示例 Just。你需要的是将它括在括号中,(Just 4),否则你的 extract 函数看起来会采用数据构造函数,而不是构造值。

在你的情况下,你会想要:

extract (Just x) = x

事实上,这是 fromJust 功能的一部分。

另一个答案解释了为什么你不能匹配函数应用程序。为此,我要补充一点,这有点像获得反函数的神奇方法。如果有一个 extract (f x) = x,那就像神奇地拥有一个 g 这样 g . f = id。在你的例子中,你定义了一个函数 succ 我认为是

succ x = x+1

现在,如果 extract (succ x) = x 是可能的,由于等式推理,extract 将是 Integer -> Integer 类型,您将神奇地构造出 succ 的逆函数,x-1.

不过,就像我上面展示的那样,可以匹配数据结构。

您可以定义一个新的数据类型,而不是函数 succInteger 上工作:

data Nat = Zero | Succ Nat

然后轻松拥有提取功能:

extra Zero = Zero
extract (Succ x) = x

请记住,您可以,并且实际上我们鼓励您对 (Just x).

之类的内容进行模式匹配

"extracting the argument from a function" 需要反转所述函数,这只有在函数是 单射 时才有可能。更重要的是,假设

square x = x*x

root (square x) = x   -- assume it works, somehow

我们应该

root (square 2)    = 2
root (square (-2)) = -2
root 4             = ???

最后一个4既是2又是-2的平方,没有一个结果可以和它联系起来。 square 函数不是单射的,所以它的反函数甚至不是函数。

更糟糕的是,由于 4 等于上面的两个方块,引用透明性要求 return 上面的两行结果相同。但事实并非如此。