-
-
Save r00k/71433db62959449762e26976261be9b7 to your computer and use it in GitHub Desktop.
-- I've successfully written a random generator for Circles. | |
randomCircle : Random.Generator Circle | |
randomCircle = | |
Random.map4 | |
Circle | |
(Random.pair (Random.float -200 200) (Random.float -200 200)) | |
(Random.float minimumRadiusLength maximumRadiusLength) | |
randomColor | |
(Random.float 0 maximumAlpha) | |
-- But now, I want a function that takes a Circle and either | |
-- returns that Circle or generates a random one. | |
sometimesRandomCircle : Circle -> Random.Generator Circle | |
sometimesRandomCircle circle = | |
-- This approach doesn't work. What might? | |
if Random.bool == True then | |
circle | |
else | |
randomCircle | |
-- I understand how to create a *fully* random Circle (or List of random Circles). | |
-- I want to return a random Circle half the time, and return the existing Circle the other half. |
But how!?
I haven't played with generators yet, so I'm not sure I'll be much help. Can you use List.map
on sometimesRandomCircle
and a list of Circle
s to get a List (Random.Generator Circle)
s? I'm looking at the docs and puzzle about how to turn that into a List Circle
, but maybe you're not supposed to with generators?
There's no obvious way to go from List (Random.Generator a) -> Random.Generator (List a)
either so...hmmm.
sometimesReplace circle =
Random.choices
[ Random.Extra.constant circle
, randomCircleGenerator
]
generateListWithRandomlyReplaceCircles listOfCircles =
let
listOfGenerators = List.map sometimesReplace listOfCircles
in
Random.Extra.together listOfGenerators
^_^
@xarvh - Thank you so much!
I'd been banging my head against this for a few hours, so it was so awesome to get unstuck.
This got me thinking a Hoogle for Elm would have helped. Happy to see there is one, and it even finds Random.Extra.flattenList
when I query for List (Random.Generator a) -> Random.Generator (List a)
.
@jmitchell - Nice find! That would indeed have helped.
Here's how I'd do it:
andThen = flip Random.andThen
swapSome : List Circle -> Random.Generator (List Circle)
swapSome circles =
let
doSwap oldCircle bool =
if bool then
Random.Extra.constant oldCircle
else
randomCircle
in
Random.list (List.length circles) Random.bool -- or use a non-uniform generator of booleans
|> andThen (\bools -> List.map2 doSwap circles bools |> Random.Extra.flattenList)
Tricky little problem though!
Progress!
I now have this function type-checking:
Now, my goal is to use that to walk a
List
ofCircles
randomly replacing some with randomly-generated newCircles
.