如:
extract (f x) = x
我想要做的是从函数或类型构造函数中提取参数,例如
extract succ 4 = 4
extract Just 4 = 4
PS。 extract(f x)= f也不起作用。
答案 0 :(得分:6)
函数式编程中的一个关键概念,尤其是纯函数式编程,是等式推理。 Haskell中的=
实际上是相等的(除了模式匹配的顺序等等)。所以当我们写
f 3 = 12
这意味着f 3
和12
实际上是同一件事 - 完全无法区分。由于extract 12
没有任何意义,extract (f 3)
也没有。
从另一个方向来看,在运行时,无法通过将某个函数应用于某个其他值来判断是否形成了某个值。提供此类信息通常非常昂贵,并且通常不会有用。
答案 1 :(得分:4)
"从函数中提取参数"需要反转所述函数,这只有当函数是 injective 时才有可能。更重要的是,假设
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
等于上述两个方格,因此参照透明度要求上述两行返回相同的结果。但情况并非如此。
答案 2 :(得分:1)
您绝对可以使用数据构造函数(例如您的示例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
的倒数,{{1 }}
尽管如上所示,可能的是与数据结构相匹配。
您可以定义一个新的数据类型,而不是处理x-1
的函数succ
:
Integer
然后轻松拥有提取功能:
data Nat = Zero | Succ Nat
请记住,可以,并且事实上鼓励他们对extra Zero = Zero
extract (Succ x) = x
之类的内容进行模式匹配。