有没有办法比较两个函数是否相等?例如,
(λx.2*x) == (λx.x+x)
应该返回 true,因为它们显然是等价的。(λx.2*x) == (λx.x+x)
应该返回 true,因为它们显然是等价的。众所周知,在一般情况下,通用函数相等性是无法判定的,因此您必须选择您感兴趣的问题子集。您可以考虑以下一些部分解决方案:
prove $ \(x::SInt32) -> 2*x .== x + x
的结果是 Q.E.D.
。请确认一下。 - Thomas M. DuBuisson这通常是不可判定的,但对于一个合适的子集,您确实可以使用SMT求解器在今天有效地解决它:
$ ghci
GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help
Prelude> :m Data.SBV
Prelude Data.SBV> (\x -> 2 * x) === (\x -> x + x :: SInteger)
Q.E.D.
Prelude Data.SBV> (\x -> 2 * x) === (\x -> 1 + x + x :: SInteger)
Falsifiable. Counter-example:
s0 = 0 :: Integer
(\x -> 2*x) == (\x -> x*2)
相等吗? - Daniel Wagner(λx.2*x)
是否等于(λx.x+x)
。在λ演算中,加法和乘法可以定义为:add = (a b c -> (a b (a b c)))
mul = (a b c -> (a (b c)))
add_x_x = (λx . (add x x))
mul_x_2 = (mul (λf x . (f (f x)))
result = (a b c -> (a b (a b c)))
(λx.(mul 2 (mul 3 x))
和(λx.(mul 6 x))
都具有相同的标准形式。或者使用带有 计算机代数库 的 C#:
MathObject f(MathObject x) => x + x;
MathObject g(MathObject x) => 2 * x;
{
var x = new Symbol("x");
Console.WriteLine(f(x) == g(x));
}
(x \[Function] x + x) == (y \[Function] 2 y)
是某些东西,它甚至不尝试。 - user5920214通常情况下,证明两个函数相等是不可判定的,但在特殊情况下仍然可以证明函数等式,就像您的问题一样。
这里是 Lean 中的一个示例证明:
def foo : (λ x, 2 * x) = (λ x, x + x) :=
begin
apply funext, intro x,
cases x,
{ refl },
{ simp,
dsimp [has_mul.mul, nat.mul],
have zz : ∀ a : nat, 0 + a = a := by simp,
rw zz }
end
在其他依赖类型的语言中,例如Coq、Agda、Idris,也可以做到同样的事情。
上述是一种策略风格的证明。实际生成的foo
(证明)的定义相当冗长,无法手写:
def foo : (λ (x : ℕ), 2 * x) = λ (x : ℕ), x + x :=
funext
(λ (x : ℕ),
nat.cases_on x (eq.refl (2 * 0))
(λ (a : ℕ),
eq.mpr
(id_locked
((λ (a a_1 : ℕ) (e_1 : a = a_1) (a_2 a_3 : ℕ) (e_2 : a_2 = a_3), congr (congr_arg eq e_1) e_2)
(2 * nat.succ a)
(nat.succ a * 2)
(mul_comm 2 (nat.succ a))
(nat.succ a + nat.succ a)
(nat.succ a + nat.succ a)
(eq.refl (nat.succ a + nat.succ a))))
(id_locked
(eq.mpr
(id_locked
(eq.rec (eq.refl (0 + nat.succ a + nat.succ a = nat.succ a + nat.succ a))
(eq.mpr
(id_locked
(eq.trans
(forall_congr_eq
(λ (a : ℕ),
eq.trans
((λ (a a_1 : ℕ) (e_1 : a = a_1) (a_2 a_3 : ℕ) (e_2 : a_2 = a_3),
congr (congr_arg eq e_1) e_2)
(0 + a)
a
(zero_add a)
a
a
(eq.refl a))
(propext (eq_self_iff_true a))))
(propext (implies_true_iff ℕ))))
trivial
(nat.succ a))))
(eq.refl (nat.succ a + nat.succ a))))))