Với định nghĩa Nat
và Sum
không có hình dạng, bạn không thể chứng minh được điều gì. Đó là bởi vì Sum
không phải là một chức năng, với cùng một lý lẽ, chúng ta có thể có kết quả khác nhau:
object Pooper {
implicit def invalidSum: Sum[_1, _1] = new Sum[_1, _1] {
type Out = _3
}
}
Nhưng nếu chúng ta định nghĩa bẩm và tổng kết một chút khác nhau:
package plusassoc
import scala.language.higherKinds
import scalaz.Leibniz
sealed trait Nat {
type Add[A <: Nat] <: Nat // 1.add(5)
}
case class Zero() extends Nat {
type Add[A <: Nat] = A
}
case class Succ[N <: Nat]() extends Nat {
type Add[A <: Nat] = Succ[N#Add[A]]
}
// a for aliases
package object a {
// Equality on nats
type ===[A <: Nat, B <: Nat] = Leibniz[Nothing, Nat, A, B]
type Plus[A <: Nat, B <: Nat] = A#Add[B]
type One = Succ[Zero]
type Two = Succ[One]
type Three = Succ[Two]
}
import a._
Các Add
(và Plus
) hiện đang hoạt động tốt ở mức loại.
Sau đó, chúng ta có thể viết bằng chứng về kết hợp của Plus
:
/*
plus-assoc : ∀ n m p → (n + (m + p)) ≡ ((n + m) + p)
plus-assoc zero m p = refl
plus-assoc (suc n) m p = cong suc (plus-assoc n m p)
*/
trait PlusAssoc[N <: Nat, M <: Nat, P <: Nat] {
val proof: Plus[N,Plus[M, P]] === Plus[Plus[N, M], P]
}
object PlusAssoc {
implicit def plusAssocZero[M <: Nat, P <: Nat]: PlusAssoc[Zero, M, P] = new PlusAssoc[Zero, M, P] {
val proof: Plus[M,P] === Plus[M,P] = Leibniz.refl
}
implicit def plusAssocSucc[N <: Nat, M <: Nat, P <: Nat](implicit
ih: PlusAssoc[N, M, P]): PlusAssoc[Succ[N], M, P] = new PlusAssoc[Succ[N], M, P] {
// For some reason scalac fails to infer right params for lift :(
val proof: Succ[Plus[N,Plus[M, P]]] === Succ[Plus[Plus[N, M], P]] = Leibniz.lift[
Nothing, Nothing,
Nat, Nat,
Succ,
Plus[N, Plus[M, P]], Plus[Plus[N, M], P]
](ih.proof)
}
}
Và như chúng tôi dựa vào implicits, chúng ta phải kiểm tra scalac rằng thực sự có thể xây dựng bằng chứng sử dụng "quy tắc" của chúng tôi:
import plusassoc._
import plusassoc.a._
import plusassoc.PlusAssoc._
implicitly[PlusAssoc[One, Two, Three]].proof
res0: ===[Plus[One,Plus[Two,Three]],Plus[Plus[One,Two],Three]] = [email protected]
// with plusassoc.a. prefix skipped
Bạn có bất kỳ bằng chứng nào bạn đã quản lý để hoàn thành bằng cách sử dụng các loại phụ thuộc của Shapeless (hoặc các phương tiện Scala khác) mà bạn có thể khoe với công chúng? –
tải xuống: http://brianmckenna.org/blog/evenodd_agda_idris_haskell_scala –