Search code examples
randomelm

How can I use map function with random number


This code is from http://elm-lang.org/edit/examples/Intermediate/Stamps.elm. I did a minor change, see below.

import Mouse
import Window
import Random

main : Signal Element
main = lift2 scene Window.dimensions clickLocations

-- for a good time, remove "sampleOn Mouse.clicks" ;)
clickLocations : Signal [(Int,Int)]
clickLocations = foldp (::) [] (sampleOn Mouse.clicks Mouse.position)

scene : (Int,Int) -> [(Int,Int)] -> Element
scene (w,h) locs =
  let p = Random.float (fps 25)
      drawPentagon p (x,y) =
          ngon 5 20 |> filled (hsla p 0.9 0.6 0.7)
                    |> move (toFloat x - toFloat w / 2, toFloat h / 2 - toFloat y)
                    |> rotate (toFloat x)
  in  layers [ collage w h (map (drawPentagon <~ p) locs) // I want to change different color each time, error here!
             , plainText "Click to stamp a pentagon." ]

How can I pass a signal when using map function?


Solution

  • In your code, you have drawPentagon <~ p which has the type Signal ((Int, Int) -> Form)

    The type of map is map : (a -> b) -> [a] -> [b] which is causing the type error. It is basically saying, that map is expecting a function a -> b but you've given it a Signal ((Int, Int) -> From).

    One way to try and accomplish what you're doing is to make p a parameter of scene and use lift3 to pass in Random.float (fps 25). So, you would end up with this:

    import Mouse
    import Window
    import Random
    
    main : Signal Element
    main = lift3 scene Window.dimensions clickLocations (Random.float (fps 25))
    
    -- for a good time, remove "sampleOn Mouse.clicks" ;)
    clickLocations : Signal [(Int,Int)]
    clickLocations = foldp (::) [] (sampleOn Mouse.clicks Mouse.position)
    
    scene : (Int,Int) -> [(Int,Int)] -> Float -> Element
    scene (w,h) locs p =
      let drawPentagon p (x,y) =
              ngon 5 20 |> filled (hsla p 0.9 0.6 0.7)
                        |> move (toFloat x - toFloat w / 2, toFloat h / 2 - toFloat y)
                        |> rotate (toFloat x)
      in  layers [ collage w h (map (drawPentagon p) locs)
                 , plainText "Click to stamp a pentagon." ]
    

    Is this what you were trying to do?