Convert Random.int to String for use in Url.Builder

Hello, I’m trying to build in a randomize button where each time a user clicks on the button, the user gets a new image from an api. The api works as https://example.com/resource/123, where I can change 123 to some number in a range. I was trying to use Url.Builder to create the url for Http.get and Random.int in a “roll” function where the function just returns a Random.Generator Int and the body is just Random.int 1 10. The problem I have is that the second argument of Url.Builder's crossOrigin is a list of String but “roll” returns a Random.Generator Int. I tried to use String.fromInt but String.fromInt needs an Int not a Random.Generator Int. The Http.get { url = crossOrigin "https://example.com/resource/" [roll] [], expect = ...}. Any help would be appreciated. Thanks!

roll : Random.Generator Int
roll = 
  Random.int 1 6

gotRandomResource : Cmd Msg
gotRandomResource =
  Http.get
    { url = crossOrigin "https://example.com/resource/" [roll] []
    , expect = Http.expectJson GotImg dataDecoder
    }

Hi!
To convert “wrapped” values (such as Maybe a or Random a), you usually want to use that module’s map function. In your case, you just need to use Random.map String.fromInt roll.

This could be a function:

randomIntToString : Random Int -> Random String
randomIntToString randomInt =
    Random.map String.fromInt randomInt
2 Likes

Thanks for the reply Augustin82. I seem to misunderstand Random. The following changes I made are as follows:

randomIntToString : Random.Generator Int -> Random.Generator String
randomIntToString randomInt =
    Random.map String.fromInt randomInt

gotRandomResource : Cmd Msg
gotRandomResource =
  Http.get
    { url = crossOrigin "https://example.com/resource/" [randomIntToString roll] []
    , expect = Http.expectJson GotImg dataDecoder
    }

However, result in a Type Mismatch where I have List (Random.Generator String) but crossOrigin needs List String. With random, we are supposed to call Random.generate on the random function in update right?

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    MorePlease ->
      (Loading, gotRandomResource)  -- Should I call `Random.generate` here?

    GotImg result ->
      case result of
        Ok url ->
          (Success url, Cmd.none)

        Err _ ->
          (Failure, Cmd.none)

I’m very new to Elm and wanted to try something I thought was relatively simple. It appears I don’t quite understand how Random works. Thank you again for the help!

You can either use Random.generate in update like you mentioned, or you can use Random.step to do it all in 1 update branch like so

let
    ( randStr, nextSeed ) =
        Random.step (randomIntToString roll) model.seed
in
( { model | seed = nextSeed }
, Http.get
    { url = crossOrigin "https://example.com/resource/" [randStr] []
    , expect = Http.expectJson GotImg dataDecoder
    }
)

This would require updating you Model and init to include a Random.Seed.

1 Like

Apologies, my answer was partial and not really helpful! Thankfully, @wolfadex did a better job than I did!

@Augustin82 and @wolfadex Thank you both for the help! I really appreciate it because I’m new to functional programming and Elm so it’s great to hear the community is so responsive, helpful, and nice.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.