Proof: Difference between revisions

7,428 bytes added ,  2 months ago
Added FreeBASIC
(Added FreeBASIC)
 
(14 intermediate revisions by 4 users not shown)
Line 28:
3.1. using built-in natural numbers:
 
<langsyntaxhighlight Lisplang="lisp">(thm (implies (and (evenp x) (evenp y))
(evenp (+ x y))))</langsyntaxhighlight>
 
=={{header|Agda}}==
<syntaxhighlight lang="agda">
<lang agda>module PeanoArithmetic where
module PeanoArithmetic where
 
-- 1.1. The natural numbers.
--
-- ℕ-formation: ℕ is set.
--
-- ℕ-introduction: 0zero ∈ ℕ,
-- a ∈ ℕ | (1 +suc a) ∈ ℕ.
--
data ℕ : Set where
zero : ℕ
1+_suc : (n : ℕ) → ℕ
 
{-# BUILTIN NATURAL ℕ #-}
{-# BUILTIN ZERO zero #-}
{-# BUILTIN SUC 1+_ #-}
 
-- 2.1. The rule of addition.
--
-- via ℕ-elimination.
--
infixl 6 _+_
_+_ : ℕ → ℕ → ℕ
0 + n = n
1+ m + n = 1+ (m + n)
 
-- 1.2. The even natural numbers.
--
data 2×ℕ : ℕ → Set where
zerozero₁ : 2×ℕ 0zero
2+_ : {m : ℕ} → 2×ℕ m → 2×ℕ (2suc +(suc m) )
 
-- 1.3. The odd natural numbers.
--
data 2×ℕ+1 : ℕ → Set where
one : 2×ℕ+1 1(suc zero)
2+_₁_ : {m : ℕ} → 2×ℕ+1 m → 2×ℕ+1 (2suc +(suc m) )
 
-- 2.1. The rule of addition.
--
-- via ℕ-elimination.
--
infixl 6 _+_
_+_ : (k : ℕ) → (n : ℕ) → ℕ
zero + n = n
(suc m) + n = suc (m + n)
 
-- 3.1. Sum of any two even numbers is even.
--
-- This function takes any two even numbers and returns their sum as an even
-- number, this is the type, i.e. logical proposition, algorithm itself is a
Line 77 ⟶ 74:
-- typechecker performs that proof (by unification, so that this is a form of
-- compile-time verification).
--
even+even≡even : {m n : ℕ} → 2×ℕ m → 2×ℕ n → 2×ℕ (m + n)
even+even≡even zero zero₁ n = n
even+even≡even (2+ m) n = 2+ (even+even≡even m n)
 
-- The identity type for ℕ (for propositional equality).
--
infix 4 _≡_
data _≡_ {A : Set} (m : A) : A → Set where
refl : m ≡ m
 
sym : {A : Set} → {m n : A} → m ≡ n → n ≡ m
sym refl = refl
 
trans : {A : Set} → {m n p : A} → m ≡ n → n ≡ p → m ≡ p
trans refl n≡p = n≡p
 
-- refl, sym and trans forms an equivalence relation.
 
cong : {A B : Set} → (f : A → B) → {m n : A} → m ≡ n → 1 +f m ≡ 1 +f n
cong f refl = refl
 
-- 3.2.1. Direct proof of the associativity of addition using propositional
-- equality.
--
+-associative : (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-associative 0 zero _ _ = refl
+-associative (1+suc m) n p = cong suc (+-associative m n p)
 
-- Proof _of_ mathematical induction on the natural numbers.
--
-- P 0, ∀ x. P x → P (1 +suc x) | ∀ x. P x.
--
ind : (P : ℕ → Set) → P 0zero → ((m : ℕ) → P m → P (1 +suc m)) → (m : ℕ) → P m
ind _ P₀ _ 0 zero = P₀
ind P P₀ next (1+suc n) = next n (ind P P₀ next n)
 
-- 3.2.2. The associativity of addition by induction (with propositional
-- equality, again).
--
+-associative′ : (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-associative′ m n p = ind P P₀ is m
Line 122 ⟶ 119:
P : ℕ → Set
P m = m + n + p ≡ m + (n + p)
P₀ : P 0zero
P₀ = refl
is : (m : ℕ) → P m → P (1 +suc m)
is _ Pi = cong suc Pi
 
-- Syntactic sugar for equational reasoning (we don't use preorders here).
Line 131 ⟶ 128:
infix 4 _≋_
data _≋_ (m n : ℕ) : Set where
reflrefl₁ : m ≡ n → m ≋ n
 
infix 1 begin_
begin_ : {m n : ℕ} → m ≋ n → m ≡ n
begin refl(refl₁ m≡n) = m≡n
 
infixr 2 _~⟨_⟩_
_~⟨_⟩_ : (m : ℕ){n p : ℕ} → m ≡ n → n ≋ p → m ≋ p
_ ~⟨ m≡n ⟩ refl(refl₁ n≡p) = reflrefl₁ (trans m≡n n≡p)
 
infix 23 _∎
_∎ : (m : ℕ) → m ≋ m
_∎ _ = reflrefl₁ refl
 
 
-- Some helper proofs.
 
m+0≡m : (m : ℕ) → m + 0zero ≡ m
m+0≡m 0 zero = refl
m+0≡m (1+suc m) = cong suc (m+0≡m m)
 
m+1+n≡1+m+n : (m n : ℕ) → m + (1 +suc n) ≡ 1 +suc (m + n)
m+1+n≡1+m+n 0 zero n = refl
m+1+n≡1+m+n (1+suc m) n = cong suc (m+1+n≡1+m+n m n)
 
-- 3.3. The commutativity of addition using equational reasoning.
--
+-commutative : (m n : ℕ) → m + n ≡ n + m
+-commutative 0 zero n = sym (m+0≡m n)
+-commutative (1+suc m) n =
begin
1+ suc m + n ~⟨ refl ⟩
1+ (m + n) ~⟨ cong (+-commutative m n)refl
1+ (n +suc (m) ~⟨ sym (m+1+n≡1+m+n n m)
n~⟨ +cong 1suc (+-commutative m n) ⟩
suc (n + m)
~⟨ sym (m+1+n≡1+m+n n m) ⟩
n + suc m
 
-- 3.4.
--
even+even≡odd : {m n : ℕ} → 2×ℕ m → 2×ℕ n → 2×ℕ+1 (m + n)
even+even≡odd zerozero₁ zerozero₁ = {!!}
even+even≡odd _ _ = {!!}
-- ^
-- That gives
--
-- ?0 : 2×ℕ+1 (zero + zero)
-- ?1 : 2×ℕ+1 (.m + .n)
--
-- but 2×ℕ+1 (zero + zero) = 2×ℕ+1 0 which is uninhabited, so that this proof
-- can not be writen.
--
 
-- The absurd (obviously uninhabited) type.
--
-- ⊥-introduction is empty.
--
data ⊥ : Set where
 
-- The negation of a proposition.
--
infix 6 ¬_
¬_ : Set → Set
Line 195 ⟶ 196:
 
-- 4.1. Disproof or proof by contradiction.
--
-- To disprove even+even≡odd we assume that even+even≡odd and derive
-- absurdity, i.e. uninhabited type.
--
even+even≢odd : {m n : ℕ} → 2×ℕ m → 2×ℕ n → ¬ 2×ℕ+1 (m + n)
even+even≢odd zerozero₁ zerozero₁ ()
even+even≢odd zerozero₁ (2+ n) (2+ m+n) = even+even≢odd zerozero₁ n m+n
even+even≢odd (2+ m) n (2+ m+n) = even+even≢odd m n m+n
 
-- 4.2.
--
-- even+even≢even : {m n : ℕ} → 2×ℕ m → 2×ℕ n → ¬ 2×ℕ (m + n)
-- even+even≢even zero zero ()
-- ^
-- rejected with the following message:
--
-- 2×ℕ zero should be empty, but the following constructor patterns
-- are valid:
Line 216 ⟶ 217:
-- when checking that the clause even+even≢even zero zero () has type
-- {m n : ℕ} → 2×ℕ m → 2×ℕ n → ¬ 2×ℕ (m + n)
--
-- </lang>
</syntaxhighlight>
 
=={{header|ATS}}==
 
=== An unusual use of ATS ===
 
The following seems similar, at least, to a completion of the task. The main problem I can see in it is it mostly consists of letting ATS do math it already knows on the ''recursion indices'' of the definition of addition. These happen to correspond to the natural numbers abstractly represented by the "prop" '''NATURAL'''.
 
Nevertheless, one can see that ATS is capable of some "abstract" reasoning. In fact, the prelude includes a recursive definition of multiplication, and in the [[Greatest_common_divisor#ATS|ATS entry for the greatest common divisor task]] I present ''practical'' (not "first principles") definitions of the gcd both by way of axioms and by recursive prop.
 
And the following does show, by total functions, how to construct a particular number (by counting up to it) and how to add (again by counting). That proofs of such things as "evens add up to evens" are then trivialized is perhaps a point ''in favor of'' ATS, ''as a systems programming language''.
 
 
<syntaxhighlight lang="ats">(* Let us do a little quasi-math in ATS, even though this is NOT an
intended use of the facilities. However, I DO consider the task a
good didactic exercise. *)
 
 
(* 1. Define the natural numbers, the even numbers, and the odd
numbers. I shall do so by recursive "prop". *)
 
dataprop NATURAL (i : int) =
| ZERO (0)
| {0 <= i} S (i + 1) of NATURAL i
 
(* Even and odd are restrictions on the recursion indices. *)
propdef EVEN (i : int) = NATURAL (2 * i)
propdef ODD (i : int) = NATURAL ((2 * i) + 1)
 
(* To construct a number. *)
prfn
make_natural {i : nat} () :<prf> NATURAL i =
let
prfun
loop {i, k : nat | k <= i} .<i - k>.
(partial_num : NATURAL k) :<prf>
NATURAL i =
sif k == i then
partial_num
else
loop (S partial_num)
in
loop (ZERO ())
end
 
prfn
make_even {i : nat} () :<prf> EVEN i =
make_natural {2 * i} ()
 
prfn
make_odd {i : nat} () :<prf> ODD i =
make_natural {(2 * i) + 1} ()
 
(* 2.1 Define addition. *)
 
prfn
addition {i, j : nat}
(i : NATURAL i,
j : NATURAL j) :<prf> NATURAL (i + j) =
let
prfun
add {k : nat | k <= j} .<j - k>.
(partial_sum : NATURAL (i + k),
shrinking : NATURAL (j - k)) :<prf>
NATURAL (i + j) =
case+ shrinking of
| ZERO () => partial_sum
| S (even_smaller) =>
add {k + 1} (S partial_sum, even_smaller)
 
prval sum = add {0} (i, j)
in
sum
end
 
prfn
addition_relation {i, j : nat} () :<prf>
(NATURAL i, NATURAL j, NATURAL (i + j)) =
let
prval i = make_natural {i} ()
prval j = make_natural {j} ()
in
(i, j, addition (i, j))
end
 
(* 3.1 Prove the sum of evens is even. *)
 
prfn
sum_of_evens {i, j : nat} () :<prf>
(EVEN i, EVEN j, EVEN (i + j)) =
addition_relation {2 * i, 2 * j} ()
 
(* or *)
 
prfn
sum_of_evens2 {i, j : nat} () :<prf>
(EVEN i, EVEN j, EVEN (i + j)) =
let
prval i = make_even {i} ()
prval j = make_even {j} ()
in
(i, j, addition (i, j))
end
 
(* 3.2 Prove addition is associative. *)
 
prfn
associativity {i, j, k : nat} () :<prf>
((NATURAL (i + j), NATURAL k, NATURAL (i + j + k)),
(NATURAL i, NATURAL (j + k), NATURAL (i + j + k))) =
(addition_relation {i + j, k} (),
addition_relation {i, j + k} ())
 
(* 3.3 Prove addition is commutative. *)
 
prfn
commutativity {i, j : nat} () :<prf>
((NATURAL i, NATURAL j, NATURAL (i + j)),
(NATURAL j, NATURAL i, NATURAL (i + j))) =
(addition_relation {i, j} (),
addition_relation {j, i} ())
 
(* 3.4 Try to prove the sum of two evens is odd. *)
 
#if 0 (* Change to 1 to see the attempted proof rejected. *)
#then
prfn
sum_of_evens_is_odd {i, j : nat} () :<prf>
(EVEN i, EVEN j, ODD (i + j)) =
(addition_relation {i, j} (),
addition_relation {j, i} ())
#endif
 
(* 4.1 Prove the sum of evens is not odd. *)
 
prfn
sum_of_evens_isnot_odd {i, j : nat} () :<prf>
(* Some might--and SHOULD--object to the use of the remainder
function here, but ATS is not really made for doing
mathematical logic. It is a systems programming language, with
some limited proof capability included as a programming aid.
If suddenly a better approach occurs to me, I might substitute
it. *)
[k : nat | k mod 2 <> 1]
(EVEN i, EVEN j, NATURAL k) =
addition_relation {2 * i, 2 * j} ()
 
(* 4.2 Try to prove the sum of evens is not even. *)
 
#if 0 (* Change to 1 to see the attempted proof rejected. *)
#then
prfn
sum_of_evens_isnot_odd {i, j : nat} () :<prf>
[k : nat | k mod 2 <> 0]
(EVEN i, EVEN j, NATURAL k) =
addition_relation {2 * i, 2 * j} ()
#endif
 
(* A little main program, for your enjoyment. *)
 
implement
main0 () =
println! ("Success!")</syntaxhighlight>
 
{{out}}
<pre>$ patscc proof-primitively.dats && ./a.out
Success!</pre>
 
=== A more usual use of ATS ===
 
Although probably I could do more precisely what is asked, and encode some formal logic in the ATS proofs language, that is not what I do below. Rosetta Code is here to show what a language can do, and so it seems better to show a bit of how ATS ''actually'' would be used.
 
In that case, addition is a poor operation upon which to base the demonstration. ''Multiplication'' would be much better, because ATS has relatively little built-in knowledge of multiplication; the operation has to be defined by axioms or recursively from addition. But I shall stick with addition, just the same.
 
Another thing to note is that ATS contains multiple sublanguages, and that proofs are ''not'' done in the same sublanguage as executable code. There are dependent types of a practical kind, but not at all in the way some other languages have dependent types as first-class objects of the full language.
 
 
<lang ATS>(* ATS does not contain a full-fledged proof language, but does
<syntaxhighlight lang="ats">(* ATS does not contain a full-fledged proof language, but does
contain enough to do a considerable amount of *informal* proof
about a program.
Line 328 ⟶ 497:
implement
main0 () =
println! ("Success!")</langsyntaxhighlight>
 
{{out}}
Line 336 ⟶ 505:
=={{header|Coq}}==
 
<langsyntaxhighlight lang="coq">(* 1.1 Define a countably infinite set of natural numbers {0, 1, 2, 3, ...}. *)
Inductive nat : Set :=
| O : nat
Line 452 ⟶ 621:
intros. apply H1. apply (even_plus_even _ _ H H0).
Qed.
</syntaxhighlight>
</lang>
 
=={{header|FreeBASIC}}==
{{trans|Phix}}
<syntaxhighlight lang="vbnet">Type Axioma
r As String
s As String
End Type
 
Dim Shared axiomas(1 To 6) As Axioma
axiomas(1).r = "even+1": axiomas(1).s = "odd"
axiomas(2).r = "even": axiomas(2).s = "2*int"
axiomas(3).r = "2*int+2*int": axiomas(3).s = "2*(int+int)"
axiomas(4).r = "(int+int)": axiomas(4).s = "int"
axiomas(5).r = "2*int": axiomas(5).s = "even"
axiomas(6).r = "odd": axiomas(6).s = "2*int+1"
 
Sub Proof(a As String, b As String)
'-- try to convert a into b using only the above axiomas
Dim As String w = a
Dim As String seen() ' -- (avoid infinite loops)
Dim As Integer i, k, hit
Do
Print Using """&"""; w
Redim Preserve seen(Lbound(seen) To Ubound(seen) + 1)
seen(Ubound(seen)) = w
If w = b Then Exit Do
hit = 0
For i = Lbound(axiomas) To Ubound(axiomas)
k = Instr(w, axiomas(i).r)
If k > 0 Then
w = Left(w, k - 1) & axiomas(i).s & Mid(w, k + Len(axiomas(i).r))
hit = i
Exit For
End If
Next i
Print " == ";
Loop Until hit = 0
Print Using "{""&"", ""&"", &}"; a; b; Iif(w = b, "true", "false")
End Sub
 
Proof("even+even", "even")
Proof("even+1", "odd")
'--bad proofs:
Proof("int", "even")
 
Sleep</syntaxhighlight>
{{out}}
<pre>"even+even"
== "2*int+even"
== "2*int+2*int"
== "2*(int+int)"
== "2*int"
== "even"
{"even+even", "even", true}
"even+1"
== "odd"
{"even+1", "odd", true}
"int"
{"int", "even", false}</pre>
 
=={{header|Go}}==
Line 464 ⟶ 693:
 
However, there is no obvious way to show that 3.2 and 3.3 must always be true (though you could argue that addition must be commutative because the 'addEven' function is symmetric in relation to its arguments). So all I've been able to do here is write functions to test these assertions for given even numbers whilst accepting that this doesn't constitute a proof for all such cases.
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 626 ⟶ 855:
 
testAssociative(genEven(numbers[7]), genEven(numbers[8]), genEven(numbers[9]))
}</langsyntaxhighlight>
 
{{out}}
Line 654 ⟶ 883:
Using [http://www.haskell.org/haskellwiki/GADT GADTs] and [http://www.haskell.org/haskellwiki/GHC/Type_families type families] it is possible to write a partial adaptation of the Agda version:
 
<langsyntaxhighlight lang="haskell">{-# LANGUAGE TypeOperators, TypeFamilies, GADTs #-}
 
module PeanoArithmetic where
Line 799 ⟶ 1,028:
--
-- since we have a "citizen" of an uninhabited type here (contradiction!).
-- </langsyntaxhighlight>
 
See also [[Proof/Haskell]] for implementation of a small theorem prover.
Line 809 ⟶ 1,038:
These ways can be combined.
 
<syntaxhighlight lang="idris">
<lang Idris>
module Proof
 
Line 943 ⟶ 1,172:
exact evenNotOdd (EvSS ex) ossx
 
</syntaxhighlight>
</lang>
 
=={{header|Isabelle}}==
<langsyntaxhighlight Isabellelang="isabelle">theory Proof
imports Main
begin
Line 1,032 ⟶ 1,261:
by(auto intro: myeven.intros)
 
end</langsyntaxhighlight>
 
=={{header|J}}==
Line 1,042 ⟶ 1,271:
So, these can be our definitions:
 
<langsyntaxhighlight Jlang="j">context=:3 :0
if. 0 = L. y do. context (,: ; ]) y return. end.
kernel=. > {: y
Line 1,074 ⟶ 1,303:
odd=: successor@even
defined=: '(zero not exists_in odd successor equals is_member_of addition even)'</langsyntaxhighlight>
 
Here, '''even''' is a function which, given a natural number, produces a corresponding even natural number. '''odd''' is a similar function which gives us odd numbers.
Line 1,093 ⟶ 1,322:
# the sum of two even numbers can never be odd.
 
<langsyntaxhighlight Jlang="j">'A B C' induction 0 :0
((even A) addition (even B)) is_member_of (even C)
((A addition B) addition C) equals (A addition (B addition C))
(A addition B) equals (B addition A)
not ((even A) addition (even B)) exists_in (odd C)
)</langsyntaxhighlight>
 
Meanwhile, here is how the invalid proofs fail:
 
<langsyntaxhighlight Jlang="j"> 'A B C' induction '((even A) addition (even B)) is_member_of (odd C)'
|assertion failure: assert</langsyntaxhighlight>
 
and
 
<langsyntaxhighlight Jlang="j"> 'A B C' induction 'not ((even A) addition (even B)) is_member_of (even C)'
|assertion failure: assert</langsyntaxhighlight>
 
 
Line 1,117 ⟶ 1,346:
We use the Go method which means that this Nim version has the same limits. When translating, we did some adjustments: for instance, we use overloading of operators which allows a more natural way to express the operations.
 
<langsyntaxhighlight Nimlang="nim">import strformat, sugar
 
type
Line 1,226 ⟶ 1,455:
testCommutative(newEvenNumber(numbers[8]), newEvenNumber(numbers[9]))
 
testAssociative(newEvenNumber(numbers[7]), newEvenNumber(numbers[8]), newEvenNumber(numbers[9]))</langsyntaxhighlight>
 
{{out}}
Line 1,251 ⟶ 1,480:
Using GADT, we can port the Coq version to OCaml.
 
<syntaxhighlight lang="ocaml">
<lang OCaml>
type zero = Zero
type 'a succ = Succ
Line 1,308 ⟶ 1,537:
plus_succ_left (plus_commutative a plus')
 
</syntaxhighlight>
</lang>
 
=={{header|Omega}}==
<langsyntaxhighlight lang="omega">data Even :: Nat ~> *0 where
EZ:: Even Z
ES:: Even n -> Even (S (S n))
Line 1,322 ⟶ 1,551:
even_plus EZ en = en
even_plus (ES em) en = ES (even_plus em en)
</syntaxhighlight>
</lang>
 
=={{header|Phix}}==
Line 1,329 ⟶ 1,558:
Clearly 3.2 and 3.3 are not attempted, and I'm not sure which of 3.4/4.1/4.2 the last axiom is
closest to, or for that matter what the difference between them is supposed to be.
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">axioms</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"even+1"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"odd"</span><span style="color: #0000FF;">},</span>
Line 1,367 ⟶ 1,596:
<span style="color: #000000;">proof</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"int"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"even"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">proof</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"even+even"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"odd"</span><span style="color: #0000FF;">)</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 1,395 ⟶ 1,624:
Via <code>#lang cur</code>.
 
<langsyntaxhighlight lang="racket">#lang cur
 
(require rackunit
Line 1,470 ⟶ 1,699:
(by-rewrite IHa)
display-focus ; show how the context and goal are after rewrite
reflexivity)</langsyntaxhighlight>
 
{{out}}
Line 1,493 ⟶ 1,722:
=={{header|Raku}}==
Partial attempt only.
<syntaxhighlight lang="raku" perl6line># 20200807 Raku programming solution (Incomplete)
 
sub check ($type, @testee) {
Line 1,535 ⟶ 1,764:
# 4.1 Prove that the addition of any two even numbers cannot be odd
# 4.2 Try to prove that the addition of any two even numbers cannot be even (it should be rejected)
</syntaxhighlight>
</lang>
{{out}}
<pre>Is 0 ∈ ℕ : True
Line 1,551 ⟶ 1,780:
Note that the only current implementation of Salmon is an interpreter that ignores proofs and doesn't try to check them, but in the future when there is an implementation that checks proofs, it should be able to check the proof in this Salmon code.
 
<langsyntaxhighlight Salmonlang="salmon">pure function even(x) returns boolean ((x in [0...+oo)) && ((x % 2) == 0));
theorem(forall(x : even, y : even) ((x + y) in even))
proof
Line 1,579 ⟶ 1,808:
(x + y) in even because type_definition(even, L10);
};
};</langsyntaxhighlight>
 
=={{header|Tcl}}==
Line 1,585 ⟶ 1,814:
 
{{works with|Tcl|8.5}}
<langsyntaxhighlight lang="tcl">package require datatype
datatype define Int = Zero | Succ val
datatype define EO = Even | Odd
Line 1,651 ⟶ 1,880:
} {
puts "\tevenOdd \[[list add $a $b]\] = [evenOdd [add $a $b]]"
}</langsyntaxhighlight>
Output:
<pre>BASE CASE
Line 1,669 ⟶ 1,898:
=={{header|Twelf}}==
 
<langsyntaxhighlight lang="twelf">nat : type.
z : nat.
s : nat -> nat.
Line 1,713 ⟶ 1,942:
%worlds () (sum-evens _ _ _ _).
%total D (sum-evens D _ _ _).
</syntaxhighlight>
</lang>
 
=={{header|Wren}}==
Line 1,719 ⟶ 1,948:
{{libheader|Wren-fmt}}
Most of what was said in the preamble to the Go entry applies equally to Wren though, as Wren is dynamically typed, we have to rely on runtime type checks.
<langsyntaxhighlight ecmascriptlang="wren">import "./fmt" for Fmt
 
// Represents a natural number.
Line 1,889 ⟶ 2,118:
 
testCommutative.call(EvenNumber.new(numbers[8]), EvenNumber.new(numbers[9]))
testAssociative.call(EvenNumber.new(numbers[7]), EvenNumber.new(numbers[8]), EvenNumber.new(numbers[9]))</langsyntaxhighlight>
 
{{out}}
2,122

edits