Skip to content

Commit e48213e

Browse files
authored
[ new ] System.Random bindings (#2368)
* [ new ] System.Random bindings * [ more ] Show functions, test * [ fix ] Nat bug, more random generators, test case * [ fix ] missing file + local gitignore * [ fix ] forgot to update the CHANGELOG
1 parent 9b4dc92 commit e48213e

File tree

16 files changed

+397
-3
lines changed

16 files changed

+397
-3
lines changed

CHANGELOG.md

+25
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,19 @@ New modules
125125
Data.Container.Indexed.Relation.Binary.Equality.Setoid
126126
```
127127

128+
* `System.Random` bindings:
129+
```agda
130+
System.Random.Primitive
131+
System.Random
132+
```
133+
134+
* Show modules:
135+
```agda
136+
Data.List.Show
137+
Data.Vec.Show
138+
Data.Vec.Bounded.Show
139+
```
140+
128141
Additions to existing modules
129142
-----------------------------
130143

@@ -265,6 +278,11 @@ Additions to existing modules
265278
nonZeroIndex : Fin n → ℕ.NonZero n
266279
```
267280

281+
* In `Data.Float.Base`:
282+
```agda
283+
_≤_ : Rel Float _
284+
```
285+
268286
* In `Data.Integer.Divisibility`: introduce `divides` as an explicit pattern synonym
269287
```agda
270288
pattern divides k eq = Data.Nat.Divisibility.divides k eq
@@ -385,6 +403,13 @@ Additions to existing modules
385403
* Added new functions in `Data.String.Base`:
386404
```agda
387405
map : (Char → Char) → String → String
406+
between : String → String → String → String
407+
```
408+
409+
* In `Data.Word.Base`:
410+
```agda
411+
_≤_ : Rel Word64 zero
412+
```
388413

389414
* Added new definition in `Relation.Binary.Construct.Closure.Transitive`
390415
```

GenerateEverything.hs

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ unsafeModules = map modToFile
7676
, "System.FilePath.Posix.Primitive"
7777
, "System.Process"
7878
, "System.Process.Primitive"
79+
, "System.Random"
80+
, "System.Random.Primitive"
7981
, "Test.Golden"
8082
, "Text.Pretty.Core"
8183
, "Text.Pretty"

src/Data/Float/Base.agda

+7-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88

99
module Data.Float.Base where
1010

11-
open import Relation.Binary.Core using (Rel)
11+
open import Data.Bool.Base using (T)
1212
import Data.Word.Base as Word
1313
import Data.Maybe.Base as Maybe
1414
open import Function.Base using (_on_; _∘_)
1515
open import Agda.Builtin.Equality
16+
open import Relation.Binary.Core using (Rel)
1617

1718
------------------------------------------------------------------------
1819
-- Re-export built-ins publically
@@ -69,3 +70,8 @@ infix 4 _≈_
6970

7071
_≈_ : Rel Float _
7172
_≈_ = _≡_ on Maybe.map Word.toℕ ∘ toWord
73+
74+
75+
infix 4 _≤_
76+
_≤_ : Rel Float _
77+
x ≤ y = T (x ≤ᵇ y)

src/Data/List/Show.agda

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Showing lists
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --cubical-compatible --safe #-}
8+
9+
module Data.List.Show where
10+
11+
open import Data.List.Base using (List; map)
12+
open import Data.String.Base using (String; between; intersperse)
13+
open import Function.Base using (_∘_)
14+
15+
show : {a} {A : Set a} (A String) (List A String)
16+
show s = between "[" "]" ∘ intersperse ", " ∘ map s

src/Data/String/Base.agda

+5-2
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,14 @@ unwords = intersperse " "
102102
unlines : List String String
103103
unlines = intersperse "\n"
104104

105+
between : String String String String
106+
between left right middle = left ++ middle ++ right
107+
105108
parens : String String
106-
parens s = "(" ++ s ++ ")"
109+
parens = between "(" ")"
107110

108111
braces : String String
109-
braces s = "{" ++ s ++ "}"
112+
braces = between "{" "}"
110113

111114
-- append that also introduces spaces, if necessary
112115
infixr 5 _<+>_

src/Data/Vec/Bounded/Show.agda

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Showing bounded vectors
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --cubical-compatible --safe #-}
8+
9+
module Data.Vec.Bounded.Show where
10+
11+
open import Data.String.Base using (String)
12+
open import Data.Vec.Bounded.Base using (Vec≤)
13+
import Data.Vec.Show as Vec
14+
open import Function.Base using (_∘_)
15+
16+
show : {a} {A : Set a} {n} (A String) (Vec≤ A n String)
17+
show s = Vec.show s ∘ Vec≤.vec

src/Data/Vec/Show.agda

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Showing vectors
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --cubical-compatible --safe #-}
8+
9+
module Data.Vec.Show where
10+
11+
import Data.List.Show as List
12+
open import Data.String.Base using (String)
13+
open import Data.Vec.Base using (Vec; toList)
14+
open import Function.Base using (_∘_)
15+
16+
show : {a} {A : Set a} {n} (A String) (Vec A n String)
17+
show s = List.show s ∘ toList

src/Data/Word/Base.agda

+4
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ _≈_ = _≡_ on toℕ
3131
infix 4 _<_
3232
_<_ : Rel Word64 zero
3333
_<_ = ℕ._<_ on toℕ
34+
35+
infix 4 _≤_
36+
_≤_ : Rel Word64 zero
37+
_≤_ = ℕ._≤_ on toℕ

src/System/Random.agda

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
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

src/System/Random/Primitive.agda

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
------------------------------------------------------------------------
2+
-- The Agda standard library
3+
--
4+
-- Primitive System.Random simple bindings to Haskell functions
5+
------------------------------------------------------------------------
6+
7+
{-# OPTIONS --cubical-compatible #-}
8+
9+
module System.Random.Primitive where
10+
11+
open import Agda.Builtin.IO using (IO)
12+
open import Agda.Builtin.Char using (Char)
13+
open import Agda.Builtin.Float using (Float)
14+
open import Agda.Builtin.Int using (Int)
15+
open import Agda.Builtin.Nat using (Nat)
16+
open import Agda.Builtin.Word using (Word64)
17+
open import Foreign.Haskell.Pair using (Pair)
18+
19+
postulate
20+
randomIO-Char : IO Char
21+
randomRIO-Char : Pair Char Char IO Char
22+
randomIO-Int : IO Int
23+
randomRIO-Int : Pair Int Int IO Int
24+
randomIO-Float : IO Float
25+
randomRIO-Float : Pair Float Float IO Float
26+
randomIO-Nat : IO Nat
27+
randomRIO-Nat : Pair Nat Nat IO Nat
28+
randomIO-Word64 : IO Word64
29+
randomRIO-Word64 : Pair Word64 Word64 IO Word64
30+
31+
{-# FOREIGN GHC import System.Random #-}
32+
33+
{-# COMPILE GHC randomIO-Char = randomIO #-}
34+
{-# COMPILE GHC randomRIO-Char = randomRIO #-}
35+
{-# COMPILE GHC randomIO-Int = randomIO #-}
36+
{-# COMPILE GHC randomRIO-Int = randomRIO #-}
37+
{-# COMPILE GHC randomIO-Float = randomIO #-}
38+
{-# COMPILE GHC randomRIO-Float = randomRIO #-}
39+
{-# COMPILE GHC randomIO-Nat = abs <$> randomIO #-}
40+
{-# COMPILE GHC randomRIO-Nat = randomRIO #-}
41+
{-# COMPILE GHC randomIO-Word64 = randomIO #-}
42+
{-# COMPILE GHC randomRIO-Word64 = randomRIO #-}

0 commit comments

Comments
 (0)