IORef.agda 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. module IORef where
  2. data Unit : Set where
  3. unit : Unit
  4. data Pair (A B : Set) : Set where
  5. pair : A -> B -> Pair A B
  6. fst : {A B : Set} -> Pair A B -> A
  7. fst (pair a b) = a
  8. snd : {A B : Set} -> Pair A B -> B
  9. snd (pair a b) = b
  10. data Nat : Set where
  11. zero : Nat
  12. suc : Nat -> Nat
  13. data Fin : Nat -> Set where
  14. fz : {n : Nat} -> Fin (suc n)
  15. fs : {n : Nat} -> Fin n -> Fin (suc n)
  16. infixr 40 _::_
  17. infixl 20 _!_
  18. data Vec (A : Set) : Nat -> Set where
  19. [] : Vec A zero
  20. _::_ : {n : Nat} -> A -> Vec A n -> Vec A (suc n)
  21. _!_ : {A : Set}{n : Nat} -> Vec A n -> Fin n -> A
  22. [] ! ()
  23. x :: _ ! fz = x
  24. _ :: xs ! (fs i) = xs ! i
  25. Loc : Nat -> Set
  26. Loc = Fin
  27. -- A universe. IORefs can store data of type el(u), for some u : U
  28. postulate
  29. U : Set
  30. el : U -> Set
  31. -- Shapes tell you what types live on the heap.
  32. Shape : Nat -> Set
  33. Shape n = Vec U n -- Fin n -> U
  34. -- Shapes can grow as you allocate new memory
  35. _||_ : {n : Nat} -> Shape n -> U -> Shape (suc n)
  36. xs || u = u :: xs
  37. infixl 40 _▻_
  38. infixl 60 _[_:=_] _[_]
  39. -- The heap maps locations to elements of the right type.
  40. data Heap : {n : Nat}(s : Shape n) -> Set where
  41. ε : Heap []
  42. _▻_ : {n : Nat}{s : Shape n}{a : U} -> Heap s -> el a -> Heap (s || a)
  43. -- Heap : {n : Nat} -> Shape n -> Set
  44. -- Heap {n} shape = (k : Fin n) -> el (shape ! k)
  45. _[_:=_] : {n : Nat}{s : Shape n} -> Heap s -> (l : Loc n) -> el (s ! l) -> Heap s
  46. ε [ () := _ ]
  47. (h ▻ _) [ fz := x ] = h ▻ x
  48. (h ▻ y) [ fs i := x ] = h [ i := x ] ▻ y
  49. _[_] : {n : Nat}{s : Shape n} -> Heap s -> (l : Loc n) -> el (s ! l)
  50. ε [ () ]
  51. (h ▻ x) [ fz ] = x
  52. (h ▻ _) [ fs i ] = h [ i ]
  53. -- (h [ fz := x ]) fz = x
  54. -- (h [ fz := x ]) (fs i) = h (fs i)
  55. -- (h [ fs i := x ]) fz = h fz
  56. -- _[_:=_] {._}{_ :: s} h (fs i) x (fs j) = _[_:=_] {s = s} (\z -> h (fs z)) i x j
  57. -- Well-scoped, well-typed IORefs
  58. data IO (A : Set) : {n m : Nat} -> Shape n -> Shape m -> Set where
  59. Return : {n : Nat}{s : Shape n} -> A -> IO A s s
  60. WriteIORef : {n m : Nat}{s : Shape n}{t : Shape m} ->
  61. (loc : Loc n) -> el (s ! loc) -> IO A s t -> IO A s t
  62. ReadIORef : {n m : Nat}{s : Shape n}{t : Shape m} ->
  63. (loc : Loc n) -> (el (s ! loc) -> IO A s t) -> IO A s t
  64. NewIORef : {n m : Nat}{s : Shape n}{t : Shape m}{u : U} ->
  65. el u -> IO A (s || u) t -> IO A s t
  66. -- Running IO programs
  67. run : {A : Set} -> {n m : Nat} -> {s : Shape n} -> {t : Shape m}
  68. -> Heap s -> IO A s t -> Pair A (Heap t)
  69. run heap (Return x) = pair x heap
  70. run heap (WriteIORef l x io) = run (heap [ l := x ]) io
  71. run heap (ReadIORef l k) = run heap (k (heap [ l ]))
  72. run heap (NewIORef x k) = run (heap ▻ x) k
  73. infixr 10 _>>=_ _>>_
  74. _>>=_ : {A B : Set}{n₁ n₂ n₃ : Nat}{s₁ : Shape n₁}{s₂ : Shape n₂}{s₃ : Shape n₃} ->
  75. IO A s₁ s₂ -> (A -> IO B s₂ s₃) -> IO B s₁ s₃
  76. Return x >>= f = f x
  77. WriteIORef r x k >>= f = WriteIORef r x (k >>= f)
  78. ReadIORef r k >>= f = ReadIORef r (\x -> k x >>= f)
  79. NewIORef x k >>= f = NewIORef x (k >>= f)
  80. _>>_ : {A B : Set}{n₁ n₂ n₃ : Nat}{s₁ : Shape n₁}{s₂ : Shape n₂}{s₃ : Shape n₃} ->
  81. IO A s₁ s₂ -> IO B s₂ s₃ -> IO B s₁ s₃
  82. a >> b = a >>= \_ -> b
  83. -- The operations without CPS
  84. data IORef : {n : Nat}(s : Shape n) -> U -> Set where
  85. ioRef : {n : Nat}{s : Shape n}(r : Loc n) -> IORef s (s ! r)
  86. return : {A : Set}{n : Nat}{s : Shape n} -> A -> IO A s s
  87. return = Return
  88. writeIORef : {n : Nat}{s : Shape n}{a : U} ->
  89. IORef s a -> el a -> IO Unit s s
  90. writeIORef (ioRef r) x = WriteIORef r x (Return unit)
  91. readIORef : {n : Nat}{s : Shape n}{a : U} -> IORef s a -> IO (el a) s s
  92. readIORef (ioRef r) = ReadIORef r Return
  93. newIORef : {n : Nat}{s : Shape n}{a : U} -> el a -> IO (IORef (s || a) a) s (s || a)
  94. newIORef x = NewIORef x (Return (ioRef fz))
  95. -- Some nice properties
  96. infix 10 _==_ _≡_
  97. data _==_ {A : Set}(x : A) : A -> Set where
  98. refl : x == x
  99. subst : {A : Set}(P : A -> Set){x y : A} -> x == y -> P y -> P x
  100. subst {A} P refl Px = Px
  101. cong : {A B : Set}(f : A -> B){x y : A} -> x == y -> f x == f y
  102. cong {A} f refl = refl
  103. trans : {A : Set}{x y z : A} -> x == y -> y == z -> x == z
  104. trans {A} refl p = p
  105. fsteq : {A B : Set}{x y : A}{z w : B} -> pair x z == pair y w -> x == y
  106. fsteq {A}{B} refl = refl
  107. -- Lemmas
  108. update-lookup : {n : Nat}{s : Shape n}(h : Heap s)(r : Loc n)(x : el (s ! r)) ->
  109. h [ r := x ] [ r ] == x
  110. update-lookup ε () _
  111. update-lookup (h ▻ _) fz x = refl
  112. update-lookup (h ▻ _) (fs i) x = update-lookup h i x
  113. update-update : {n : Nat}{s : Shape n}(h : Heap s)(r : Loc n)(x y : el (s ! r)) ->
  114. h [ r := x ] [ r := y ] == h [ r := y ]
  115. update-update ε () _ _
  116. update-update (h ▻ _) fz x y = refl
  117. update-update (h ▻ z) (fs i) x y = cong (\ ∙ -> ∙ ▻ z) (update-update h i x y)
  118. -- Equality of monadic computations
  119. data _≡_ {A : Set}{n m : Nat}{s : Shape n}{t : Shape m}(io₁ io₂ : IO A s t) : Set where
  120. eqIO : ((h : Heap s) -> run h io₁ == run h io₂) -> io₁ ≡ io₂
  121. uneqIO : {A : Set}{n m : Nat}{s : Shape n}{t : Shape m}{io₁ io₂ : IO A s t} ->
  122. io₁ ≡ io₂ -> (h : Heap s) -> run h io₁ == run h io₂
  123. uneqIO (eqIO e) = e
  124. -- Congruence properties
  125. cong->> : {A B : Set}{n₁ n₂ n₃ : Nat}{s₁ : Shape n₁}{s₂ : Shape n₂}{s₃ : Shape n₃}
  126. {io₁₁ io₁₂ : IO A s₁ s₂}{io₂₁ io₂₂ : A -> IO B s₂ s₃} ->
  127. io₁₁ ≡ io₁₂ -> ((x : A) -> io₂₁ x ≡ io₂₂ x) -> io₁₁ >>= io₂₁ ≡ io₁₂ >>= io₂₂
  128. cong->> {A}{B}{s₁ = s₁}{s₂}{s₃}{io₁₁}{io₁₂}{io₂₁}{io₂₂}(eqIO eq₁) eq₂ =
  129. eqIO (prf io₁₁ io₁₂ io₂₁ io₂₂ eq₁ eq₂)
  130. where
  131. prf : {n₁ n₂ n₃ : Nat}{s₁ : Shape n₁}{s₂ : Shape n₂}{s₃ : Shape n₃}
  132. (io₁₁ io₁₂ : IO A s₁ s₂)(io₂₁ io₂₂ : A -> IO B s₂ s₃) ->
  133. ((h : Heap s₁) -> run h io₁₁ == run h io₁₂) ->
  134. ((x : A) -> io₂₁ x ≡ io₂₂ x) ->
  135. (h : Heap s₁) -> run h (io₁₁ >>= io₂₁) == run h (io₁₂ >>= io₂₂)
  136. prf (Return x) (Return y) k₁ k₂ eq₁ eq₂ h =
  137. subst (\ ∙ -> run h (k₁ ∙) == run h (k₂ y)) x=y (uneqIO (eq₂ y) h)
  138. where
  139. x=y : x == y
  140. x=y = fsteq (eq₁ h)
  141. prf (WriteIORef r₁ x₁ k₁) (Return y) k₂ k₃ eq₁ eq₂ h = ?
  142. -- ... boring proofs
  143. -- Monad laws
  144. -- boring...
  145. -- IO laws
  146. new-read : {n : Nat}{s : Shape n}{a : U}(x : el a) ->
  147. newIORef {s = s} x >>= readIORef ≡
  148. newIORef x >> return x
  149. new-read x = eqIO \h -> refl
  150. write-read : {n : Nat}{s : Shape n}{a : U}(r : IORef s a)(x : el a) ->
  151. writeIORef r x >> readIORef r
  152. ≡ writeIORef r x >> return x
  153. write-read (ioRef r) x =
  154. eqIO \h -> cong (\ ∙ -> pair ∙ (h [ r := x ]))
  155. (update-lookup h r x)
  156. write-write : {n : Nat}{s : Shape n}{a : U}(r : IORef s a)(x y : el a) ->
  157. writeIORef r x >> writeIORef r y
  158. ≡ writeIORef r y
  159. write-write (ioRef r) x y =
  160. eqIO \h -> cong (\ ∙ -> pair unit ∙) (update-update h r x y)
  161. -- Some separation properties would be nice