# Randomness at the beginnings of time (function randrun)

I was using `randrun`, and wanted to apply the usual trick of time-shifting, to get different (pseudo) random sequences.

I am surprised that near time 0, sequences are not permuted at all. Also, for small shifts, there are long consecutive subsequences:

``````do
let p =
( cat \$ replicate 100
\$ n (fmap fromIntegral
\$ 0.1 -- <== change this (increase slowly)
-- up to 0.5 : contains long increasing runs
-- above 1.0 : fully random
~> randrun 12)
)
resetCycles
d1 \$ stack [ p
, slow 1.01 p -- to get the "Piano Phase" effect, just for show
]
# s "superpiano"
# room 0.8
``````

Focusing on `randrun`:

``````ghci> flip queryArc (Arc 0 1) \$ randrun 10
[(0>⅒)|0,(⅒>⅕)|1,(⅕>3/10)|2,(3/10>⅖)|3,(⅖>½)|4,(½>⅗)|5,(⅗>7/10)|6,(7/10>⅘)|7,(⅘>9/10)|8,(9/10>1)|9]

ghci> flip queryArc (Arc 0.5 1.5) \$ randrun 10
[(½>⅗)|5,(⅗>7/10)|6,(7/10>⅘)|7,(⅘>9/10)|8,(9/10>1)|9,(1>1⅒)|3,(1⅒>1⅕)|1,(1⅕>13/10)|2,(13/10>1⅖)|5,(1⅖>1½)|4]
``````

a- ha, it is `run 10` from time 0 to 1, and random only after that? Intentionally?

[the following is a bit technical ... in short, there is a problem in my code (time shift is useless), and there's a problem in `randrun` implementation (ignores Arc endpoint), and I propose an alternative. I can make a PR if someone confirms that the idea works, and would like to use it.]

• time-shifting: this only makes sense for the continuous pattern (`rand`), not fot the discretized one (`randrun` is discrete). E.g., two different sequences, events (for both) at each fourth:
``````segment 4 (0.1 ~> irand 10)
-- [(0>⅒)-¼|9,0-(⅒>¼)|5,(¼>½)|7,(½>¾)|5,(¾>1)|0]
segment 4 (0.2 ~> irand 10)
--  [(0>⅕)-¼|8,0-(⅕>¼)|4,(¼>½)|1,(½>¾)|8,(¾>1)|6]
``````

something quite different:

`````` 0.1 ~> (segment 4 \$ irand 10)
-- [-117/20-(0>⅒)|3,(⅒>7/20)|3,(7/20>⅗)|6,(⅗>17/20)|1,(17/20>1)-1⅒|3]
0.2 ~> (segment 4 \$ irand 10)
-- [-119/20-(0>⅕)|3,(⅕>9/20)|3,(9/20>7/10)|6,(7/10>19/20)|1,(19/20>1)-1⅕|3]
``````
• non-randomness for `randrun` at time zero: I think the reason is
``````randrun n' =
splitQueries \$ Pattern (\(State a@(Arc s _) _) -> events a \$ sam s)
.....................................^^^^^^^^
``````

uses just `s` (start of arc) and ignores the arc's end.

NB - Each time I see (in Tidal sources) an implementation that works on queries directly, I wonder - is it really necessary to break the abstraction barrier? I am dreaming of a world where `data Pattern a` is opaque (constructor is not exported), and the module that contains `data Pattern a = ...` is as small as possible)

• I tried to find a "more abstract" implementation. Maybe this:
``````rands :: Fractional a => Int -> Pattern [a]
rands k = Pattern \$ \(State a@(Arc s e) _)
-> [Event (Context []) Nothing a (map realToFrac \$ (timeToRands ((e + s)/2) k :: [Double]))]

randrun' :: Int -> Pattern Int
randrun' n = segment 1 (rands n) >>= \ rs ->
let go [] [] = []
go (r:rs) xs =
let i = floor (r * fromIntegral (length xs))
(pre, p:ost) = splitAt i xs
in  p : go rs (pre <> ost)
in  fastcat \$ map pure \$ go rs [0 .. n-1]
``````

perhaps `rands` can be built in some better way (I just copied `rand` and replaced `timeToRand` with `timeToRands`).

• If we want a different "random" realization (for events at the same time), then time-shifting does not help, see above. To be able to do this, we can
``````randrun'' :: Int -> Pattern (Pattern Int)
randrun'' n = flip fmap (rands n) \$ \ rs ->
let go [] [] = []
go (r:rs) xs =
let i = floor (r * fromIntegral (length xs))
(pre, p:ost) = splitAt i xs
in  p : go rs (pre <> ost)
in  fastcat \$ map pure \$ go rs [0 .. n-1]
``````

note on the result type: the outer pattern is continuous (it refers to `rand`), and the inner pattern is discrete. In the application, we can then

`````` unwrap  \$ segment 1  \$ 0.4  ~> randrun'' 12
``````

and by changing the shift, we get different values while keeping the timing.