|
| 1 | +------------------------------------------------------------------------ |
| 2 | +-- The Agda standard library |
| 3 | +-- |
| 4 | +-- *Pseudo-random* number generation |
| 5 | +------------------------------------------------------------------------ |
| 6 | + |
| 7 | +{-# OPTIONS --cubical-compatible --guardedness #-} |
| 8 | + |
| 9 | +module System.Random where |
| 10 | + |
| 11 | +import System.Random.Primitive as Prim |
| 12 | + |
| 13 | +open import Data.Bool.Base using (T) |
| 14 | +open import Data.Nat.Base using (ℕ; z≤n) hiding (module ℕ) |
| 15 | +open import Foreign.Haskell.Pair using (_,_) |
| 16 | +open import Function.Base using (_$_; _∘_) |
| 17 | +open import IO.Base using (IO; lift; lift!; _<$>_; _>>=_; pure) |
| 18 | +import IO.Effectful as IO |
| 19 | +open import Level using (0ℓ; suc; _⊔_; lift) |
| 20 | +open import Relation.Binary.Core using (Rel) |
| 21 | + |
| 22 | +------------------------------------------------------------------------ |
| 23 | +-- Ranged generation shall return proofs |
| 24 | + |
| 25 | +record InBounds {a r} {A : Set a} (_≤_ : Rel A r) (lo hi : A) : Set (a ⊔ r) where |
| 26 | + constructor _∈[_,_] |
| 27 | + field |
| 28 | + value : A |
| 29 | + .isLowerBound : lo ≤ value |
| 30 | + .isUpperBound : value ≤ hi |
| 31 | + |
| 32 | +RandomRIO : ∀ {a r} {A : Set a} (_≤_ : Rel A r) → Set (suc (a ⊔ r)) |
| 33 | +RandomRIO {A = A} _≤_ = (lo hi : A) → .(lo ≤ hi) → IO (InBounds _≤_ lo hi) |
| 34 | + |
| 35 | +------------------------------------------------------------------------ |
| 36 | +-- Instances |
| 37 | + |
| 38 | +module Char where |
| 39 | + |
| 40 | + open import Data.Char.Base using (Char; _≤_) |
| 41 | + |
| 42 | + randomIO : IO Char |
| 43 | + randomIO = lift Prim.randomIO-Char |
| 44 | + |
| 45 | + randomRIO : RandomRIO _≤_ |
| 46 | + randomRIO lo hi _ = do |
| 47 | + value ← lift (Prim.randomRIO-Char (lo , hi)) |
| 48 | + pure (value ∈[ trustMe , trustMe ]) |
| 49 | + where postulate trustMe : ∀ {A} → A |
| 50 | + |
| 51 | +module Float where |
| 52 | + |
| 53 | + open import Data.Float.Base using (Float; _≤_) |
| 54 | + |
| 55 | + randomIO : IO Float |
| 56 | + randomIO = lift Prim.randomIO-Float |
| 57 | + |
| 58 | + randomRIO : RandomRIO _≤_ |
| 59 | + randomRIO lo hi _ = do |
| 60 | + value ← lift (Prim.randomRIO-Float (lo , hi)) |
| 61 | + pure (value ∈[ trustMe , trustMe ]) |
| 62 | + where postulate trustMe : ∀ {A} → A |
| 63 | + |
| 64 | +module ℤ where |
| 65 | + |
| 66 | + open import Data.Integer.Base using (ℤ; _≤_) |
| 67 | + |
| 68 | + randomIO : IO ℤ |
| 69 | + randomIO = lift Prim.randomIO-Int |
| 70 | + |
| 71 | + randomRIO : RandomRIO _≤_ |
| 72 | + randomRIO lo hi _ = do |
| 73 | + value ← lift (Prim.randomRIO-Int (lo , hi)) |
| 74 | + pure (value ∈[ trustMe , trustMe ]) |
| 75 | + where postulate trustMe : ∀ {A} → A |
| 76 | + |
| 77 | +module ℕ where |
| 78 | + |
| 79 | + open import Data.Nat.Base using (ℕ; _≤_) |
| 80 | + |
| 81 | + randomIO : IO ℕ |
| 82 | + randomIO = lift Prim.randomIO-Nat |
| 83 | + |
| 84 | + randomRIO : RandomRIO _≤_ |
| 85 | + randomRIO lo hi _ = do |
| 86 | + value ← lift (Prim.randomRIO-Nat (lo , hi)) |
| 87 | + pure (value ∈[ trustMe , trustMe ]) |
| 88 | + where postulate trustMe : ∀ {A} → A |
| 89 | + |
| 90 | +module Word64 where |
| 91 | + |
| 92 | + open import Data.Word.Base using (Word64; _≤_) |
| 93 | + |
| 94 | + randomIO : IO Word64 |
| 95 | + randomIO = lift Prim.randomIO-Word64 |
| 96 | + |
| 97 | + randomRIO : RandomRIO _≤_ |
| 98 | + randomRIO lo hi _ = do |
| 99 | + value ← lift (Prim.randomRIO-Word64 (lo , hi)) |
| 100 | + pure (value ∈[ trustMe , trustMe ]) |
| 101 | + where postulate trustMe : ∀ {A} → A |
| 102 | + |
| 103 | +module Fin where |
| 104 | + |
| 105 | + open import Data.Nat.Base as ℕ using (suc; NonZero; z≤n; s≤s) |
| 106 | + import Data.Nat.Properties as ℕ |
| 107 | + open import Data.Fin.Base using (Fin; _≤_; fromℕ<; toℕ) |
| 108 | + import Data.Fin.Properties as Fin |
| 109 | + |
| 110 | + randomIO : ∀ {n} → .{{NonZero n}} → IO (Fin n) |
| 111 | + randomIO {n = n@(suc _)} = do |
| 112 | + suc k ∈[ lo≤k , k≤hi ] ← ℕ.randomRIO 1 n (s≤s z≤n) |
| 113 | + pure (fromℕ< k≤hi) |
| 114 | + |
| 115 | + toℕ-cancel-InBounds : ∀ {n} {lo hi : Fin n} → |
| 116 | + InBounds ℕ._≤_ (toℕ lo) (toℕ hi) → |
| 117 | + InBounds _≤_ lo hi |
| 118 | + toℕ-cancel-InBounds {n} {lo} {hi} (k ∈[ toℕlo≤k , k≤toℕhi ]) = |
| 119 | + let |
| 120 | + .k<n : k ℕ.< n |
| 121 | + k<n = ℕ.≤-<-trans k≤toℕhi (Fin.toℕ<n hi) |
| 122 | + |
| 123 | + .lo≤k : lo ≤ fromℕ< k<n |
| 124 | + lo≤k = Fin.toℕ-cancel-≤ $ let open ℕ.≤-Reasoning in begin |
| 125 | + toℕ lo ≤⟨ toℕlo≤k ⟩ |
| 126 | + k ≡⟨ Fin.toℕ-fromℕ< k<n ⟨ |
| 127 | + toℕ (fromℕ< k<n) ∎ |
| 128 | + |
| 129 | + .k≤hi : fromℕ< k<n ≤ hi |
| 130 | + k≤hi = Fin.toℕ-cancel-≤ $ let open ℕ.≤-Reasoning in begin |
| 131 | + toℕ (fromℕ< k<n) ≡⟨ Fin.toℕ-fromℕ< k<n ⟩ |
| 132 | + k ≤⟨ k≤toℕhi ⟩ |
| 133 | + toℕ hi ∎ |
| 134 | + |
| 135 | + in fromℕ< k<n ∈[ lo≤k , k≤hi ] |
| 136 | + |
| 137 | + randomRIO : ∀ {n} → RandomRIO {A = Fin n} _≤_ |
| 138 | + randomRIO {n} lo hi p = do |
| 139 | + k ← ℕ.randomRIO (toℕ lo) (toℕ hi) (Fin.toℕ-mono-≤ p) |
| 140 | + pure (toℕ-cancel-InBounds k) |
| 141 | + |
| 142 | +module List {a} {A : Set a} (rIO : IO A) where |
| 143 | + |
| 144 | + open import Data.List.Base using (List; replicate) |
| 145 | + open import Data.List.Effectful using (module TraversableA) |
| 146 | + |
| 147 | + -- Careful: this can generate very long lists! |
| 148 | + -- You may want to use Vec≤ instead. |
| 149 | + randomIO : IO (List A) |
| 150 | + randomIO = do |
| 151 | + lift n ← lift! ℕ.randomIO |
| 152 | + TraversableA.sequenceA IO.applicative $ replicate n rIO |
| 153 | + |
| 154 | +module Vec {a} {A : Set a} (rIO : IO A) (n : ℕ) where |
| 155 | + |
| 156 | + open import Data.Vec.Base using (Vec; replicate) |
| 157 | + open import Data.Vec.Effectful using (module TraversableA) |
| 158 | + |
| 159 | + randomIO : IO (Vec A n) |
| 160 | + randomIO = TraversableA.sequenceA IO.applicative $ replicate n rIO |
| 161 | + |
| 162 | +module Vec≤ {a} {A : Set a} (rIO : IO A) (n : ℕ) where |
| 163 | + |
| 164 | + open import Data.Vec.Bounded.Base using (Vec≤; _,_) |
| 165 | + |
| 166 | + randomIO : IO (Vec≤ A n) |
| 167 | + randomIO = do |
| 168 | + lift (len ∈[ _ , len≤n ]) ← lift! (ℕ.randomRIO 0 n z≤n) |
| 169 | + vec ← Vec.randomIO rIO len |
| 170 | + pure (vec , len≤n) |
| 171 | + |
| 172 | +module String where |
| 173 | + |
| 174 | + open import Data.String.Base using (String; fromList) |
| 175 | + |
| 176 | + -- Careful: this can generate very long lists! |
| 177 | + -- You may want to use String≤ instead. |
| 178 | + randomIO : IO String |
| 179 | + randomIO = fromList <$> List.randomIO Char.randomIO |
| 180 | + |
| 181 | +module String≤ (n : ℕ) where |
| 182 | + |
| 183 | + import Data.Vec.Bounded.Base as Vec≤ |
| 184 | + open import Data.String.Base using (String; fromList) |
| 185 | + |
| 186 | + randomIO : IO String |
| 187 | + randomIO = fromList ∘ Vec≤.toList <$> Vec≤.randomIO Char.randomIO n |
| 188 | + |
| 189 | +open import Data.Char.Base using (Char; _≤_) |
| 190 | + |
| 191 | +module RangedString≤ (a b : Char) .(a≤b : a ≤ b) (n : ℕ) where |
| 192 | + |
| 193 | + import Data.Vec.Bounded.Base as Vec≤ |
| 194 | + open import Data.String.Base using (String; fromList) |
| 195 | + |
| 196 | + randomIO : IO String |
| 197 | + randomIO = |
| 198 | + fromList ∘ Vec≤.toList ∘ Vec≤.map InBounds.value |
| 199 | + <$> Vec≤.randomIO (Char.randomRIO a b a≤b) n |
0 commit comments