-
-
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. |
Thanks @anicholson. That helped clarify some things, but I'm still having trouble figuring out how to write sometimesRandomCircle.
Progress!
I now have this function type-checking:
sometimesRandomCircle : Circle -> Random.Generator Circle
sometimesRandomCircle circle =
let
circle' = Random.Extra.constant circle
in
Random.bool `Random.andThen` \b -> if b then circle' else randomCircleNow, my goal is to use that to walk a List of Circles randomly replacing some with randomly-generated new Circles.
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 Circles 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!
@r00k Check out @xarvh's wonderful talk on Elm's generators: https://xarvh.github.io/talk-generators/#0