Built with doc-gen4, running Lean4. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑Ctrl+↓to navigate, Ctrl+πŸ–±οΈto focus. On Mac, use Cmdinstead of Ctrl.
import Mt.Utils.Nat

namespace Mt

/-- Class to represent 'reservations'

  Reservations are the main method for reasoning about inter-thread behaviour.
  
  Basic idea: Only threads with a certain reservation are allowed to do certain
  things. In many cases, some operation cannot be done atomically. Instead,
  a thread needs to do several steps. Using reservations, the thread can keep
  track about how many of those steps it has already accomplished. Other
  threads have no way to manipulate each other's reservation, only their own.

  For reasoning, the reservations of all threads have to be taken into account.
  However, we want:
  * The order of the other threads should not matter
  * It should not matter if there are 10 other threads, or only one which
    achieved those reservations
  
  As a consequence, we require an addition operator for reservations. Invariants
  used for reasoning may use both the shared state and the sum of all
  reservations, but not individual reservations. Each thread has to guarantee the
  invariant, but it only knows about its own reservation, i.e. it has a lower
  bound on the reservation, but nothing more. Therefore, it's actions are limited
  by the reservation it has already achieved on its own.

  ### Example:
  * There is one shared `Nat` variable `x`
  * Each thread performs the following three steps:
    - generate a random variable `n : Nat`
    - increase `x` by `n + 1` atomically
    - decrease `x` by `n` atomically
  * We want to reason that - in the end - `x` is never zero.

    Solution: We introduce a `reservation : Nat` reservation which keeps track of how much
    we have increased `x`. Therefore, the have the invariant βˆ‘reservation = x.
    Now, we can easily reason about the thread:
  * Step 1: Generating the random number has no effect on the shared variable
  * Step 2: We increase `x` by `n + 1` and assign `reservation :=n + 1`. Since the
    reservations of the other threads have not changed, the invariant still holds
  * Step 3: Since no other thread can affect our reservation, we still know that
    `reservation = n + 1`. Because of our invariant, we also know
    `x = βˆ‘reservation β‰₯ reservation = n + 1`. Therefore, we can safely decrease both `x`
    and `reservation` by `n` and we still have `x > 0`
-/
class 
IsReservation: Type β†’ Type
IsReservation
(
T: Type
T
:
Type: Type 1
Type
) extends
Add: Type ?u.6 β†’ Type ?u.6
Add
T: Type
T
,
Lean.IsAssociative: {Ξ± : Sort ?u.10} β†’ (Ξ± β†’ Ξ± β†’ Ξ±) β†’ Type
Lean.IsAssociative
(@
HAdd.hAdd: {Ξ± : Type ?u.14} β†’ {Ξ² : Type ?u.13} β†’ {Ξ³ : Type ?u.12} β†’ [self : HAdd Ξ± Ξ² Ξ³] β†’ Ξ± β†’ Ξ² β†’ Ξ³
HAdd.hAdd
T: Type
T
T: Type
T
T: Type
T
_),
Lean.IsCommutative: {Ξ± : Sort ?u.37} β†’ (Ξ± β†’ Ξ± β†’ Ξ±) β†’ Type
Lean.IsCommutative
(@
HAdd.hAdd: {Ξ± : Type ?u.41} β†’ {Ξ² : Type ?u.40} β†’ {Ξ³ : Type ?u.39} β†’ [self : HAdd Ξ± Ξ² Ξ³] β†’ Ξ± β†’ Ξ² β†’ Ξ³
HAdd.hAdd
T: Type
T
T: Type
T
T: Type
T
_) where
empty: {T : Type} β†’ [self : IsReservation T] β†’ T
empty
:
T: Type
T
empty_add: βˆ€ {T : Type} [self : IsReservation T] (t : T), IsReservation.empty + t = t
empty_add
: βˆ€
t: T
t
:
T: Type
T
,
empty: T
empty
+
t: T
t
=
t: T
t
/-- Specification for a multithreading system This specification specifies the context for threads but not the threads itself. Threads encode a specification in their type. Only threads with the same specification can be executed in parallel -/ structure
Spec: Type 1
Spec
where
State: Spec β†’ Type
State
:
Type: Type 1
Type
Reservation: Spec β†’ Type
Reservation
:
Type: Type 1
Type
[
is_reservation: (self : Spec) β†’ IsReservation self.Reservation
is_reservation
:
IsReservation: Type β†’ Type
IsReservation
Reservation: Type
Reservation
]
validate: (self : Spec) β†’ self.Reservation β†’ self.State β†’ Prop
validate
:
Reservation: Type
Reservation
->
State: Type
State
->
Prop: Type
Prop
end Mt namespace Mt
instance: IsReservation Nat
instance
:
IsReservation: Type β†’ Type
IsReservation
Nat: Type
Nat
where assoc :=
Nat.add_assoc: βˆ€ (n m k : Nat), n + m + k = n + (m + k)
Nat.add_assoc
comm :=
Nat.add_comm: βˆ€ (n m : Nat), n + m = m + n
Nat.add_comm
empty :=
0: ?m.816
0
empty_add :=
Nat.zero_add: βˆ€ (n : Nat), 0 + n = n
Nat.zero_add
def
LowerBound: Type
LowerBound
:=
Nat: Type
Nat
instance: Add LowerBound
instance
:
Add: Type ?u.897 β†’ Type ?u.897
Add
LowerBound: Type
LowerBound
:=⟨
Nat.max: Nat β†’ Nat β†’ Nat
Nat.max
⟩ instance
LowerBound.instance: IsReservation LowerBound
LowerBound.instance
:
IsReservation: Type β†’ Type
IsReservation
LowerBound: Type
LowerBound
where assoc :=
Utils.Nat.max_assoc: βˆ€ (a b c : Nat), Nat.max (Nat.max a b) c = Nat.max a (Nat.max b c)
Utils.Nat.max_assoc
comm :=
Utils.Nat.max_comm: βˆ€ (a b : Nat), Nat.max a b = Nat.max b a
Utils.Nat.max_comm
empty :=(
0: ?m.958
0
:
Nat: Type
Nat
) empty_add :=
Utils.Nat.zero_max: βˆ€ (a : Nat), Nat.max 0 a = a
Utils.Nat.zero_max
structure
UnitReservation: UnitReservation
UnitReservation
instance :
IsReservation: Type β†’ Type
IsReservation
UnitReservation: Type
UnitReservation
where add := Ξ»
_: ?m.1270
_
_: ?m.1273
_
=>
⟨⟩: UnitReservation
⟨⟩
assoc :=

βˆ€ (a b c : UnitReservation), a + b + c = a + (b + c)
a✝, b✝, c✝: UnitReservation


a✝ + b✝ + c✝ = a✝ + (b✝ + c✝)

βˆ€ (a b c : UnitReservation), a + b + c = a + (b + c)
a✝, b✝, c✝: UnitReservation


a✝ + b✝ + c✝ = a✝ + (b✝ + c✝)

βˆ€ (a b c : UnitReservation), a + b + c = a + (b + c)

Goals accomplished! πŸ™
comm :=

βˆ€ (a b : UnitReservation), a + b = b + a
a✝, b✝: UnitReservation


a✝ + b✝ = b✝ + a✝

βˆ€ (a b : UnitReservation), a + b = b + a
a✝, b✝: UnitReservation


a✝ + b✝ = b✝ + a✝

βˆ€ (a b : UnitReservation), a + b = b + a

Goals accomplished! πŸ™
empty :=
⟨⟩: UnitReservation
⟨⟩
empty_add :=

βˆ€ (t : UnitReservation), { } + t = t

{ } + t✝ = t✝

βˆ€ (t : UnitReservation), { } + t = t

{ } + t✝ = t✝

βˆ€ (t : UnitReservation), { } + t = t

Goals accomplished! πŸ™
inductive
Lock: Type β†’ Type
Lock
(
T: Type
T
:
Type: Type 1
Type
) where |
Unlocked: {T : Type} β†’ Lock T
Unlocked
|
Locked: {T : Type} β†’ T β†’ Lock T
Locked
:
T: Type
T
->
Lock: Type β†’ Sort ?u.1353
Lock
T: Type
T
|
Invalid: {T : Type} β†’ Lock T
Invalid
def
Lock.is_locked: {T : Type} β†’ Lock T β†’ Bool
Lock.is_locked
{
T: Type
T
:
Type: Type 1
Type
} :
Lock: Type β†’ Type
Lock
T: Type
T
->
Bool: Type
Bool
|
Locked: {T : Type} β†’ T β†’ Lock T
Locked
_ =>
true: Bool
true
| _ =>
false: Bool
false
def
Lock.is_locked_and_valid: {T : Type} β†’ (T β†’ Prop) β†’ Lock T β†’ Prop
Lock.is_locked_and_valid
{
T: Type
T
:
Type: Type 1
Type
} (
valid: T β†’ Prop
valid
:
T: Type
T
->
Prop: Type
Prop
) :
Lock: Type β†’ Type
Lock
T: Type
T
->
Prop: Type
Prop
|
Locked: {T : Type} β†’ T β†’ Lock T
Locked
s: T
s
=>
valid: T β†’ Prop
valid
s: T
s
| _ =>
False: Prop
False
def
Lock.is_unlocked: {T : Type} β†’ Lock T β†’ Bool
Lock.is_unlocked
{
T: Type
T
:
Type: Type 1
Type
} :
Lock: Type β†’ Type
Lock
T: Type
T
->
Bool: Type
Bool
|
Unlocked: {T : Type} β†’ Lock T
Unlocked
=>
true: Bool
true
| _ =>
false: Bool
false
def
Lock.add: {T : Type} β†’ Lock T β†’ Lock T β†’ Lock T
Lock.add
{
T: Type
T
:
Type: Type 1
Type
} :
Lock: Type β†’ Type
Lock
T: Type
T
->
Lock: Type β†’ Type
Lock
T: Type
T
->
Lock: Type β†’ Type
Lock
T: Type
T
|
Unlocked: {T : Type} β†’ Lock T
Unlocked
,
a: Lock T
a
=>
a: Lock T
a
|
a: Lock T
a
,
Unlocked: {T : Type} β†’ Lock T
Unlocked
=>
a: Lock T
a
| _, _ =>
Invalid: {T : Type} β†’ Lock T
Invalid
theorem
Lock.eq_of_is_unlocked: βˆ€ {T : Type} {r : Lock T}, is_unlocked r = true β†’ r = Unlocked
Lock.eq_of_is_unlocked
{
T: Type
T
:
Type: Type 1
Type
} {
r: Lock T
r
:
Lock: Type β†’ Type
Lock
T: Type
T
} :
r: Lock T
r
.
is_unlocked: {T : Type} β†’ Lock T β†’ Bool
is_unlocked
β†’
r: Lock T
r
=
Lock.Unlocked: {T : Type} β†’ Lock T
Lock.Unlocked
:=
T: Type

r: Lock T


is_unlocked r = true β†’ r = Unlocked
T: Type


Unlocked
is_unlocked Unlocked = true β†’ Unlocked = Unlocked
T: Type

a✝: T


Locked
is_unlocked (Locked a✝) = true β†’ Locked a✝ = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked
T: Type

r: Lock T


is_unlocked r = true β†’ r = Unlocked
T: Type


Unlocked
is_unlocked Unlocked = true β†’ Unlocked = Unlocked
T: Type


Unlocked
is_unlocked Unlocked = true β†’ Unlocked = Unlocked
T: Type

a✝: T


Locked
is_unlocked (Locked a✝) = true β†’ Locked a✝ = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked
T: Type


Unlocked
Unlocked = Unlocked
T: Type


Unlocked
is_unlocked Unlocked = true β†’ Unlocked = Unlocked
T: Type

a✝: T


Locked
is_unlocked (Locked a✝) = true β†’ Locked a✝ = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked
T: Type


Unlocked
Unlocked = Unlocked
T: Type


Unlocked
is_unlocked Unlocked = true β†’ Unlocked = Unlocked
T: Type

a✝: T


Locked
is_unlocked (Locked a✝) = true β†’ Locked a✝ = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked

Goals accomplished! πŸ™
T: Type

r: Lock T


is_unlocked r = true β†’ r = Unlocked
T: Type

a✝: T


Locked
is_unlocked (Locked a✝) = true β†’ Locked a✝ = Unlocked
T: Type

a✝: T


Locked
is_unlocked (Locked a✝) = true β†’ Locked a✝ = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked
T: Type

a✝¹: T


Locked
Locked a✝¹ = Unlocked
T: Type

a✝: T


Locked
is_unlocked (Locked a✝) = true β†’ Locked a✝ = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked
T: Type

a✝¹: T


Locked
Locked a✝¹ = Unlocked
T: Type

a✝: T


Locked
is_unlocked (Locked a✝) = true β†’ Locked a✝ = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked

Goals accomplished! πŸ™
T: Type

r: Lock T


is_unlocked r = true β†’ r = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked
T: Type


Invalid
Invalid = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked
T: Type


Invalid
Invalid = Unlocked
T: Type


Invalid
is_unlocked Invalid = true β†’ Invalid = Unlocked

Goals accomplished! πŸ™
instance: {T : Type} β†’ Add (Lock T)
instance
{
T: Type
T
:
Type: Type 1
Type
} :
Add: Type ?u.2811 β†’ Type ?u.2811
Add
(
Lock: Type β†’ Type
Lock
T: Type
T
) :=⟨
Lock.add: {T : Type} β†’ Lock T β†’ Lock T β†’ Lock T
Lock.add
⟩ theorem
Lock.unlocked_add: βˆ€ {T : Type} (a : Lock T), Unlocked + a = a
Lock.unlocked_add
{
T: Type
T
:
Type: Type 1
Type
} : βˆ€
a: Lock T
a
:
Lock: Type β†’ Type
Lock
T: Type
T
,
Unlocked: {T : Type} β†’ Lock T
Unlocked
+
a: Lock T
a
=
a: Lock T
a
:=
T: Type


βˆ€ (a : Lock T), Unlocked + a = a
T: Type

a: Lock T


Unlocked + a = a
T: Type


βˆ€ (a : Lock T), Unlocked + a = a
T: Type

a: Lock T


Unlocked + a = a
T: Type


βˆ€ (a : Lock T), Unlocked + a = a
T: Type


Unlocked
Unlocked + Unlocked = Unlocked
T: Type

a✝: T


Locked
Unlocked + Locked a✝ = Locked a✝
T: Type


Invalid
Unlocked + Invalid = Invalid
T: Type

a: Lock T


Unlocked + a = a
T: Type


Unlocked
Unlocked + Unlocked = Unlocked
T: Type

a✝: T


Locked
Unlocked + Locked a✝ = Locked a✝
T: Type


Invalid
Unlocked + Invalid = Invalid
T: Type

a: Lock T


Unlocked + a = a

Goals accomplished! πŸ™
theorem
Lock.add_unlocked: βˆ€ {T : Type} (a : Lock T), a + Unlocked = a
Lock.add_unlocked
{
T: Type
T
:
Type: Type 1
Type
} : βˆ€
a: Lock T
a
:
Lock: Type β†’ Type
Lock
T: Type
T
,
a: Lock T
a
+
Unlocked: {T : Type} β†’ Lock T
Unlocked
=
a: Lock T
a
:=
T: Type


βˆ€ (a : Lock T), a + Unlocked = a
T: Type

a: Lock T


a + Unlocked = a
T: Type


βˆ€ (a : Lock T), a + Unlocked = a
T: Type

a: Lock T


a + Unlocked = a
T: Type


βˆ€ (a : Lock T), a + Unlocked = a
T: Type


Unlocked
Unlocked + Unlocked = Unlocked
T: Type

a✝: T


Locked
Locked a✝ + Unlocked = Locked a✝
T: Type


Invalid
Invalid + Unlocked = Invalid
T: Type

a: Lock T


a + Unlocked = a
T: Type


Unlocked
Unlocked + Unlocked = Unlocked
T: Type

a✝: T


Locked
Locked a✝ + Unlocked = Locked a✝
T: Type


Invalid
Invalid + Unlocked = Invalid
T: Type

a: Lock T


a + Unlocked = a

Goals accomplished! πŸ™
theorem
Lock.invalid_add: βˆ€ {T : Type} (a : Lock T), Invalid + a = Invalid
Lock.invalid_add
{
T: Type
T
:
Type: Type 1
Type
} : βˆ€
a: Lock T
a
:
Lock: Type β†’ Type
Lock
T: Type
T
,
Invalid: {T : Type} β†’ Lock T
Invalid
+
a: Lock T
a
=
Invalid: {T : Type} β†’ Lock T
Invalid
:=
T: Type


βˆ€ (a : Lock T), Invalid + a = Invalid
T: Type

a: Lock T


Invalid + a = Invalid
T: Type


βˆ€ (a : Lock T), Invalid + a = Invalid
T: Type

a: Lock T


Invalid + a = Invalid
T: Type


βˆ€ (a : Lock T), Invalid + a = Invalid
T: Type


Unlocked
Invalid + Unlocked = Invalid
T: Type

a✝: T


Locked
Invalid + Locked a✝ = Invalid
T: Type


Invalid
Invalid + Invalid = Invalid
T: Type

a: Lock T


Invalid + a = Invalid
T: Type


Unlocked
Invalid + Unlocked = Invalid
T: Type

a✝: T


Locked
Invalid + Locked a✝ = Invalid
T: Type


Invalid
Invalid + Invalid = Invalid
T: Type

a: Lock T


Invalid + a = Invalid

Goals accomplished! πŸ™
theorem
Lock.add_comm: βˆ€ {T : Type} (a b : Lock T), a + b = b + a
Lock.add_comm
{
T: Type
T
:
Type: Type 1
Type
} : βˆ€
a: Lock T
a
b: Lock T
b
:
Lock: Type β†’ Type
Lock
T: Type
T
,
a: Lock T
a
+
b: Lock T
b
=
b: Lock T
b
+
a: Lock T
a
:=
T: Type


βˆ€ (a b : Lock T), a + b = b + a
T: Type

a, b: Lock T


a + b = b + a
T: Type


βˆ€ (a b : Lock T), a + b = b + a
T: Type

b: Lock T


Unlocked
Unlocked + b = b + Unlocked
T: Type

b: Lock T

a✝: T


Locked
Locked a✝ + b = b + Locked a✝
T: Type

b: Lock T


Invalid
Invalid + b = b + Invalid
T: Type

a, b: Lock T


a + b = b + a
T: Type

b: Lock T


Unlocked
Unlocked + b = b + Unlocked
T: Type

b: Lock T

a✝: T


Locked
Locked a✝ + b = b + Locked a✝
T: Type

b: Lock T


Invalid
Invalid + b = b + Invalid
T: Type

a, b: Lock T


a + b = b + a
T: Type


Invalid.Unlocked
Invalid + Unlocked = Unlocked + Invalid
T: Type

a✝: T


Invalid.Locked
Invalid + Locked a✝ = Locked a✝ + Invalid
T: Type


Invalid.Invalid
Invalid + Invalid = Invalid + Invalid
T: Type

b: Lock T


Unlocked
Unlocked + b = b + Unlocked
T: Type

a✝: T


Locked.Unlocked
Locked a✝ + Unlocked = Unlocked + Locked a✝
T: Type

a✝¹, a✝: T


Locked.Locked
Locked a✝¹ + Locked a✝ = Locked a✝ + Locked a✝¹
T: Type

a✝: T


Locked.Invalid
Locked a✝ + Invalid = Invalid + Locked a✝
T: Type

b: Lock T


Unlocked
Unlocked + b = b + Unlocked

Goals accomplished! πŸ™
theorem
Lock.add_assoc: βˆ€ {T : Type} (a b c : Lock T), a + b + c = a + (b + c)
Lock.add_assoc
{
T: Type
T
:
Type: Type 1
Type
} : βˆ€
a: Lock T
a
b: Lock T
b
c: Lock T
c
:
Lock: Type β†’ Type
Lock
T: Type
T
,
a: Lock T
a
+
b: Lock T
b
+
c: Lock T
c
=
a: Lock T
a
+ (
b: Lock T
b
+
c: Lock T
c
) :=
T: Type


βˆ€ (a b c : Lock T), a + b + c = a + (b + c)
T: Type

a, b, c: Lock T


a + b + c = a + (b + c)
T: Type


βˆ€ (a b c : Lock T), a + b + c = a + (b + c)
T: Type

b, c: Lock T


Unlocked
Unlocked + b + c = Unlocked + (b + c)
T: Type

b, c: Lock T

a✝: T


Locked
Locked a✝ + b + c = Locked a✝ + (b + c)
T: Type

b, c: Lock T


Invalid
Invalid + b + c = Invalid + (b + c)
T: Type

a, b, c: Lock T


a + b + c = a + (b + c)
T: Type

b, c: Lock T


Unlocked
Unlocked + b + c = Unlocked + (b + c)
T: Type

b, c: Lock T

a✝: T


Locked
Locked a✝ + b + c = Locked a✝ + (b + c)
T: Type

b, c: Lock T


Invalid
Invalid + b + c = Invalid + (b + c)
T: Type

a, b, c: Lock T


a + b + c = a + (b + c)
T: Type

c: Lock T

a✝: T


Locked.Unlocked
Locked a✝ + Unlocked + c = Locked a✝ + (Unlocked + c)
T: Type

c: Lock T

a✝¹, a✝: T


Locked.Locked
Locked a✝¹ + Locked a✝ + c = Locked a✝¹ + (Locked a✝ + c)
T: Type

c: Lock T

a✝: T


Locked.Invalid
Locked a✝ + Invalid + c = Locked a✝ + (Invalid + c)
T: Type

b, c: Lock T

a✝: T


Locked
Locked a✝ + b + c = Locked a✝ + (b + c)
T: Type

c: Lock T


Invalid.Unlocked
Invalid + Unlocked + c = Invalid + (Unlocked + c)
T: Type

c: Lock T

a✝: T


Invalid.Locked
Invalid + Locked a✝ + c = Invalid + (Locked a✝ + c)
T: Type

c: Lock T


Invalid.Invalid
Invalid + Invalid + c = Invalid + (Invalid + c)
T: Type

b, c: Lock T

a✝: T


Locked
Locked a✝ + b + c = Locked a✝ + (b + c)
T: Type


Unlocked.Invalid.Unlocked
Unlocked + Invalid + Unlocked = Unlocked + (Invalid + Unlocked)
T: Type

a✝: T


Unlocked.Invalid.Locked
Unlocked + Invalid + Locked a✝ = Unlocked + (Invalid + Locked a✝)
T: Type


Unlocked.Invalid.Invalid
Unlocked + Invalid + Invalid = Unlocked + (Invalid + Invalid)
T: Type

c: Lock T


Invalid.Invalid
Invalid + Invalid + c = Invalid + (Invalid + c)
T: Type

a✝: T


Locked.Invalid.Unlocked
Locked a✝ + Invalid + Unlocked = Locked a✝ + (Invalid + Unlocked)
T: Type

a✝¹, a✝: T


Locked.Invalid.Locked
Locked a✝¹ + Invalid + Locked a✝ = Locked a✝¹ + (Invalid + Locked a✝)
T: Type

a✝: T


Locked.Invalid.Invalid
Locked a✝ + Invalid + Invalid = Locked a✝ + (Invalid + Invalid)
T: Type

c: Lock T


Invalid.Invalid
Invalid + Invalid + c = Invalid + (Invalid + c)

Goals accomplished! πŸ™
instance: {T : Type} β†’ IsReservation (Lock T)
instance
{
T: Type
T
:
Type: Type 1
Type
} :
IsReservation: Type β†’ Type
IsReservation
(
Lock: Type β†’ Type
Lock
T: Type
T
) where assoc :=
Lock.add_assoc: βˆ€ {T : Type} (a b c : Lock T), a + b + c = a + (b + c)
Lock.add_assoc
comm :=
Lock.add_comm: βˆ€ {T : Type} (a b : Lock T), a + b = b + a
Lock.add_comm
empty :=
Lock.Unlocked: {T : Type} β†’ Lock T
Lock.Unlocked
empty_add :=
Lock.unlocked_add: βˆ€ {T : Type} (a : Lock T), Lock.Unlocked + a = a
Lock.unlocked_add
end Mt