First some code:
import Random
import Window
writeRandom x = lift asText (Random.range 0 x <| every second)
upperLimit = 300
-- upperLimit = Window.width -- How can i use this instead?
main = writeRandom upperLimit
Ultimately I'm trying to get random points on the screen, but I can't figure out how to pass Window.height and Window.width to Random.range. I don't think I can 'lift' Random.range, since it already returns a signal. If I try I get a type error:
Type Error: 'main' must have type Element or (Signal Element).
Instead 'main' has type:
Signal (Signal Element)
And I'm not sure that the opposite of lift (lower?) exists, or even makes sense.
Thanks
You are correct in supposing that an opposite of lower doesn't make sense.
In this particular case, the builtin Random library is builtin because it's a wrapper around a native JavaScript call. This is the reason for the Signal
return type, to keep the code pure. And even then, it's not completely well-behaved.
To get the kind of random range you want, you'll need a different random number generator. There is a community library that was published only a few days ago, that'll probably answer your needs. You can check it out of GitHub yourself, or use the elm-get
tool.
Your code would become something like (untested!):
import Window
import Generator
import Generator.Standard as GStd
randomSeed = 12346789
writeRandom : Signal Int -> Signal Element
writeRandom x =
let update high (_, gen) = Generator.int32Range (0,high) gen
start = (0, GStd.generator randomSeed)
input = sampleOn (every second) x
result = fst <~ foldp update start input
in lift asText result
upperLimit = Window.width
main = writeRandom upperLimit
In writeRandom
, you use foldp
to keep the latest random-number generator. In update
you use this to get a new random number and a new generator for the next time. The input of x
is updated every second by using sampleOn (every second)
. The fst <~
part is to remove the random number generator, since you only want the random number.