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 3
和12
实际上是同一个东西——完全没有区别。由于 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
.
不过,就像我上面展示的那样,可以匹配数据结构。
您可以定义一个新的数据类型,而不是函数 succ
在 Integer
上工作:
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 上面的两行结果相同。但事实并非如此。
如:
extract (f x) = x
我想做的是从函数或类型构造函数中提取参数,例如
extract succ 4 = 4
extract Just 4 = 4
ps。 extract (f x) = f 也不行。
函数式编程,尤其是纯函数式编程中的一个关键概念是等式推理。 Haskell 中的 =
是实际相等(抛开模式匹配的顺序等)。所以当我们写
f 3 = 12
这意味着f 3
和12
实际上是同一个东西——完全没有区别。由于 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
.
不过,就像我上面展示的那样,可以匹配数据结构。
您可以定义一个新的数据类型,而不是函数 succ
在 Integer
上工作:
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 上面的两行结果相同。但事实并非如此。