an illustration in 5 languages
\(P(0)\)
\(P(k)\to P(++k)\)
\(n:\mathbb{N}\)
\(P(n)\)
"Base Case"
"Induction Hypothesis"
"Number to use"
"Consequence"
1 is odd.
If k is odd then k+2 is odd.
4=2+2
Nothing to say, 4=2+2 doesn't match the induction hypothesis nor the base case.
1 is odd.
If k is odd then k+2 is odd.
5=(1+2)+2
If 1+2 is odd then (1+2)+2 is odd.
If 1 is odd then 1+2 is odd.
1 is odd.
5 is odd.
// Form the type
sealed trait List[A]
// Introduce base case
case [] extends List[A]
// Introduct Induction Hypothesis
case (head : A) :: (tail : List[A]) extends List[A]
def length( as : List[A]) : Int =
// Eliminate inductive type
as match {
// Compute base case, 0 lenght
case [] -> 0
// Compute Resursion via "Inductive Hypothesis":
// if length(tail)=k then length(head::tail) = ++k
case head :: tail -> ++length(tail)
}\(P(0)\)
\(P(0),....,P(k)\to P(++k)\)
\(n:\mathbb{N}\)
\(P(n)\)
"Base Case"
"Induction Hypothesis"
"Number to use"
"Consequence"
A triangle has 180 degrees.
If k-gon has \(180(k-2)\) degree then a (k+1)-gon has \(180((k+1)-2)\) degrees.
n=5=++(++3)=(3+1)+1
// Form the type
sealed trait List[A]
// Introduce base case
case [] extends List[A]
// Introduct Induction Hypothesis
case (head : A) :: (tail : List[A]) extends List[A]
def length( as : List[A]) : Int =
// Eliminate inductive type
as match {
// Compute base case, 0 lenght
case [] -> 0
// Compute Resursion via "Inductive Hypothesis":
// if length(tail)=k then length(head::tail) = ++k
case head :: tail -> ++length(tail)
}Every subset \(F\) of events \(E\) has minimal ones \(\partial E\)
If \(P(\partial F)\) then \(P(F)\)
\(P(\partial E)\)
\(e\in E\)
\(P(e)\)
"Boundary Case"
"Induction Hypothesis"
"Event to use"
"Consequence"
"Well-founded"
E=Computer network.
If you can hack one user then you can hack his inbox.
Someone hacked you.
Your entire network is hacked; and you have just been fired.
def guess(n) =
n match {
case Even -> return "You loose"
case Odd -> guess(n div 3)
case Zero -> return "You win!"
}> guess(6) You loose
> guess(5) guess(1) guess(0) You loose
> guess(0) You loose
def guess(n) =
n match {
case Zero -> return "You win!"
case Even -> return "You loose"
case Odd -> guess(n div 3)
}> guess(6) You loose
> guess(5) guess(1) guess(0) You win
> guess(0) You win
open import Data.Nat using (ℕ)
open import Data.String using (String)
open import Data.Sum using (_⊎_; inj₁; inj₂)
module Bits where
-- Binary digits up ↑ and down ↓
data 𝔹 : Set where
↑ : 𝔹
↓ : 𝔹
-- Use of a bit
asFive : 𝔹 → ℕ ⊎ String
asFive ↑ = inj₁ 5
asFive ↓ = inj₂ "Five"Agda (1999) (a Haskell family 1990)
open import Data.Nat using (ℕ)
open import Data.String using (String)
open import Data.Sum using (_⊎_; inj₁; inj₂)
module Bits where
-- Binary digits up ↑ and down ↓
data Trit : Set where
a : Trit
b : Trit
c : Trit
-- Do something
thing : Trit → ℕ ⊎ String
thing a = inj₁ 5
thing c = inj₂ "Five"
thing _ = inj₁ 42Agda (1999) (a Haskell family 1990)
(* Binary digits up and down *)
type bit =
| Up
| Down
(* Sum type for either natural number or string *)
type nat_or_string =
| Left of int
| Right of string
(* Use of a bit. *)
let asFive = function
| Up -> Left 5
| Down -> Right "Five"
OCaml (1996) (an ML family 1973)
// Binary digits up and down
sealed trait 𝔹
case object ↑ extends 𝔹
case object ↓ extends 𝔹
// Use of a bit
def asFive(bit: 𝔹): Either[Int, String] = bit match {
case ↑ => Left(5)
case ↓ => Right("Five")
}Scala (2004) (an Java family 1995)
import java.util.Objects;
class Bits {
// Binary digits up and down using sealed interface
sealed interface 𝔹 permits Up, Down {}
final class Up() implements 𝔹 {}
final class Down implements 𝔹 {}
// Sum type equivalent using sealed interface
sealed interface Either<L, R> permits Left, Right {}
record Left<L, R>(L value) implements Either<L, R> {}
record Right<L, R>(R value) implements Either<L, R> {}
// Use of a bit.
Either<Integer, String> asFive(𝔹 bit) {
return switch (bit) {
case Up up -> new Left<>(5);
case Down down -> new Right<>("Five");
};
}
}Java (since 1995,
but feature here added in 2021 (JDK 16))
#include <variant>
#include <string>
#include <iostream>
// Binary digits up and down
enum class 𝔹 {
↑, // up
↓ // down
};
// Sum type equivalent using std::variant
using EitherIntString = std::variant<int, std::string>;
// Use of a bit
EitherIntString asFive(𝔹 bit) {
switch (bit) {
case 𝔹::↑:
return 5;
case 𝔹::↓:
return std::string("Five");
}
// Should never reach here with complete switch
return 0;
}
C++ (1983, but pattern matching still not standard, alternatives shown!)
data 𝔹 : Set where
↑ : 𝔹 -- Voltage up
↓ : 𝔹 -- Voltage down
type bit =
| zero
| onesealed trait Bit
case Zero extends Bit
case One extends Bit
enum Bit {
ZERO, ONE;
}
abstract sealed class Bit {}
final class Zero() extends Bit {}
final class One() extends Bit {}
public sealed class Bit
permits Zero, One {
...
}
{
}
not : Bit -> Bit
not zero = one
not one = zeronot b = match b with
| zero -> one
| one -> zerodef not( b : Bit ) : Bit =
b match {
case Zero() => One()
case One() => Zero()
} select(b) {
case Bit.ZERO -> Bit.ONE
case Bit.ONE -> Bit.ZERO
}
if ( b instanceof Zero )
return new One();
if ( b instanceof One )
return new Zero();Bit not( Bit b ) {
return select( b ) {
case Zero() -> new One();
case One() -> new Zero();
}
}data List A where
nil : List A
cons : (a : A) -> (tail : List A) -> List Atype 'a list =
| Nil
| Cons of 'a * 'a listsealed trait List[A+]
case Nil extends List[Any]
case Cons( a : A, tail : List[A]) extends List[A]
public sealed class List<A> {}
class final Nil() extends List<Class> {}
class final Cons(<A> a,
List<A> tail) extends List<A> {}