What does it mean for software to be “correct”?
There are three main criteria:
How to make it practical: exceptions, contracts, loops.
These things are still needed..
A convincing demonstration of correctness being impossible as long as the mechanism is regarded as a black box, our only hope lies in not regarding the mechanism as a black box.
By using types to shed light into your assertions and invariants your compiler is then a proof assistant.
... Prove it otherwise ...
Let's define a TYPE to be True if it has values, and False if it has no values.
A Type's inhabitence can also be unknown, and it's truth value is undecidable.
Let's choose to only work with types that are True.
... Prove it otherwise ...
//In other words:
def true: Unit = () // not true: Boolean
def false: Nothing = ??? // not false: Boolean
... and these ideas are shaping new foundations for mathematics ...
We can prove logical statements by constructing elements of types
def intToString: Int => String = _.toString
def times2: Int => Int = a => a * a
def always[A]: A => Option[A] = Some(_)
Constructive Logic as types...
// Constructive Connectives
type False = Nothing
type And[A, B] = (A, B)
type Or[A, B] = Either[A, B]
type Implication[A, B] = A => B
Proofs, or code paths, like any good story, or program run have a beginning, a middle and an end:
Assumptions.
Our domain types.
Statements in order.
Functions.
The goal.
A value.
Let's write some proofs code.
... can constructivism be practical? ...
def decode[A](s: String): A
def decode[A](s: String): Either[Error, A]
Excercises: http://bit.ly/cp-total-exercises
def squareRoot(a: Int): Int = ...
def squareRoot(a: UnsignedInt): UnisignedInt = ...
Excercises: http://bit.ly/cp-total-exercises
var x = 5 = 3
val x = 5 = 3 // Exception
if (x = 1) // Oops
r = open("w")
r = open("y") // Oops
Exercises: http://bit.ly/cp-transparency-excercises
def cpsSystemTime: () => Timestamp = ...
def systemTime: IO[Timestamp] = ...
systemTime()
doSomething()
sleep(1)
systemTime()
doSomethingElse()
Exercises: http://bit.ly/cp-transparency-excercises
Avoid recursion
//hmmm: http://stainless.epfl.ch/doc/intro.html
def use[A](a: A): A = use(a)
def sum(l: List[Int]): Int = l.fold(0)(_ + _)
Turing's Halting Problem ≃ Gödel's Incompleteness Theorems
Excercises: http://bit.ly/cp-termination-excercises
Avoid loops
def use[A](a: A): A = while (true) { ... }; a
val fib = 0 #:: fib.scanLeft(1)(_ + _)
Excercises: http://bit.ly/cp-termination-excercises
Yes.
Category Theory is the study of composition.
Constructive programming is a family of of Proof calculi aligned with goal of productive software development.
sealed trait Person
case class Teacher(name: String, students: List[Person])
extends Person
case class Student(name: String, teacher: Teacher)
extends Person
type Pay = Double
type Fee = Double
type Balance = Double
def payCalc: Teacher => Pay = _.students.foldLeft(0.0){
case (pay, t:Teacher) => pay + 0.1 * payCalc(t)
case (pay, s:Student) => pay + 2.5
}
def feeCalc: Student => Fee = _ match {
case Student(_, t) => 1.10 * payCalc(t) / t.students.length
}
def feeBalance: Fee => Balance = identity
def payBalance: Pay => Balance = - _
def findPerson(name: String):
Option[Either[Student, Teacher]] = ???
def findPerson(name: String):
Option[Either[Student, Teacher]] = ???
val names: List[String] = ???
val schoolBalance: Balance = names
.flatMap(findPerson)
.map(feeCalc.choose(payCalc))
.foldMap(feeBalance.choice(payBalance))
// res: Balance = 0.0
http://cheng.staff.shef.ac.uk/proofguide/proofguide.pdf
http://math.andrej.com/wp-content/uploads/2017/12/Spartan-Type-Theory.pdf
http://ecee.colorado.edu/ecen5533/fall11/reading/free.pdf
http://tesi.cab.unipd.it/56555/1/tesi_Mengato_def.pdf
http://www.lix.polytechnique.fr/~lengrand/Work/Teaching/MPRI/Notes.pdf
https://en.m.wikipedia.org/wiki/Curry%E2%80%93Howard_correspondence
https://www.youtube.com/watch?v=IOiZatlZtGU
http://math.andrej.com/2016/08/09/what-is-a-formal-proof/
https://github.com/Chymyst/curryhoward