1
------------------------------------------------------------------------
2
------------------------------------------------------------------------
4
open import Relation.Binary
5
open import Relation.Binary.OrderMorphism
6
open import Relation.Binary.PropositionalEquality
7
import Relation.Binary.Props.StrictTotalOrder as STOProps
8
open import Data.Product
11
module MonadPostulates where
14
-- Input string positions.
17
_<P_ : Rel Position zero
18
posOrdered : IsStrictTotalOrder _≡_ _<P_
22
Input : Position -> Set
24
-- In order to be able to store results in a memo table (and avoid
25
-- having to lift the table code to Set1) the result types have to
26
-- come from the following universe:
31
-- Memoisation keys. These keys must uniquely identify the
32
-- computation that they are associated with, when paired up with
33
-- the current input string position.
35
Key : let PosPoset = STOProps.poset
36
(record { Carrier = _ ; _≈_ = _; _<_ = _
37
; isStrictTotalOrder = posOrdered })
38
MonoFun = PosPoset ⇒-Poset PosPoset in
39
MonoFun -> Result -> Set
40
_≈'_ _<_ : Rel (∃₂ Key) zero
41
keyOrdered : IsStrictTotalOrder _≈'_ _<_
43
-- Furthermore the underlying equality needs to be strong enough.
45
funsEqual : _≈'_ =[ proj₁ ]⇒ _≡_
46
resultsEqual : _≈'_ =[ (\rfk -> proj₁ (proj₂ rfk)) ]⇒ _≡_
50
open STOProps (record { Carrier = _ ; _≈_ = _; _<_ = _
51
; isStrictTotalOrder = posOrdered })
53
import IndexedMap as Map -- renaming (Map to MemoTable)
54
open import Category.Monad
55
open import Category.Monad.State
56
import Data.List as List; open List using (List)
57
open import Data.Unit hiding (poset; _≤_)
59
open import Data.Maybe hiding (Eq)
60
open import Relation.Binary.Product.StrictLex
61
open import Relation.Binary.Product.Pointwise
62
import Relation.Binary.On as On
64
------------------------------------------------------------------------
67
MonoFun = poset ⇒-Poset poset
69
------------------------------------------------------------------------
73
Index = Position × MonoFun × Result
75
data MemoTableKey : Index -> Set where
76
key : forall {f r} (key : Key f r) pos -> MemoTableKey (pos , f , r)
79
Input≤ : Position -> Set
80
Input≤ pos = ∃ \pos′ -> pos′ ≤ pos × Input pos′
84
Value (pos , f , r) = List (⟦ r ⟧ × Input≤ (fun f pos))
87
shuffle : ∃ MemoTableKey -> Position × ∃₂ Key
88
shuffle ((pos , f , r) , key k .pos) = (pos , f , r , k)
91
Eq : Rel (∃ MemoTableKey) _
92
Eq = _≡_ ×-Rel _≈'_ on shuffle
94
Lt : Rel (∃ MemoTableKey) _
95
Lt = ×-Lex _≡_ _<P_ _<_ on shuffle
97
isOrdered : IsStrictTotalOrder Eq Lt
98
isOrdered = On.isStrictTotalOrder shuffle
99
(posOrdered ×-isStrictTotalOrder keyOrdered)
101
indicesEqual′ : Eq =[ proj₁ ]⇒ _≡_
102
indicesEqual′ {((_ , _ , _) , key _ ._)}
103
{((_ , _ , _) , key _ ._)} (eq₁ , eq₂) =
104
cong₂ _,_ eq₁ (cong₂ _,_ (funsEqual eq₂) (resultsEqual eq₂))
106
open Map isOrdered (\{k₁} {k₂} -> indicesEqual′ {k₁} {k₂}) Value
109
------------------------------------------------------------------------
113
module MemoState = RawMonadState (StateMonadState MemoTable)
116
module List = RawMonadPlus List.ListMonadPlus
122
Inner R = State MemoTable (List R)
124
InnerMonadPlus : RawMonadPlus Inner
125
InnerMonadPlus = record
128
{ return = \x -> return (List.return x)
129
; _>>=_ = \m f -> List.concat <$> (List.mapM monad f =<< m)
133
; _∣_ = \m₁ m₂ -> List._∣_ <$> m₁ ⊛ m₂
138
InnerMonadState : RawMonadState MemoTable Inner
139
InnerMonadState = record
140
{ monad = RawMonadPlus.monad InnerMonadPlus
141
; get = List.return <$> get
142
; put = \s -> List.return <$> put s
146
open RawMonadPlus InnerMonadPlus public
147
open RawMonadState InnerMonadState public
148
using (get; put; modify)
153
P : MonoFun -> Set -> Set
154
P f A = forall {n} -> Input n -> IM.Inner (A × Input≤ (fun f n))
156
-- Memoises the computation, assuming that the key is sufficiently
159
memoise : forall {f r} -> Key f r -> P f ⟦ r ⟧ -> P f ⟦ r ⟧
160
memoise k p {pos} xs =
161
let open IM in helper =<< lookup k′ <$> get
168
helper : Maybe (Value i) -> State MemoTable (Value i)
169
helper (just ris) = return ris where open MemoState
170
helper nothing = p xs >>= \ris ->
171
modify (insert k′ ris) >>
175
-- Other monadic operations.
177
return : forall {A} -> A -> P idM A
178
return a = \xs -> IM.return (a , _ , refl , xs)
180
_>>=_ : forall {A B f g} -> P f A -> (A -> P g B) -> P (g ∘M f) B
181
_>>=_ {g = g} m₁ m₂ xs =
182
m₁ xs ⟨ IM._>>=_ ⟩ \ays ->
184
le = proj₁ $ proj₂ $ proj₂ ays
185
ys = proj₂ $ proj₂ $ proj₂ ays in
186
fix le ⟨ IM._<$>_ ⟩ m₂ a ys
188
lemma : forall {i j k} -> j ≤ k -> i ≤ fun g j -> i ≤ fun g k
189
lemma j≤k i≤gj = trans i≤gj (monotone g j≤k)
191
fix : forall {A i j} -> i ≤ j ->
192
A × Input≤ (fun g i) ->
194
fix le = map-× id (map-Σ id (map-× (lemma le) id))
196
∅ : forall {A} -> P idM A
199
_∣_ : forall {A f} -> P f A -> P f A -> P f A
200
m₁ ∣ m₂ = \xs -> IM._∣_ (m₁ xs) (m₂ xs)
202
put : forall {n} -> Input n -> P (constM n) ⊤
203
put xs = \_ -> IM.return (_ , _ , refl , xs)
205
modify : forall {A f} ->
206
(forall {n} -> Input n -> A × Input (fun f n)) ->
208
modify g xs = IM.return (proj₁ gxs , _ , refl , proj₂ gxs)