In a PureScript Halogen project, I would like to set the state to a random number, but how do I extract the value? The normal
r <- randomInt 1 10
does not compile when it's inside the eval function.
module Main where
import Prelude
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Random (randomInt, RANDOM)
import Halogen as H
import Halogen.HTML.Events.Indexed as HE
import Halogen.HTML.Indexed as HH
import Halogen.Util (runHalogenAff, awaitBody)
type State = { n::Int }
initialState :: State
initialState = { n: 3}
data Query a = NewRandom a
ui :: forall e. H.Component { n :: Int } Query e
ui =
H.component { render, eval }
where
render :: State -> H.ComponentHTML Query
render state =
HH.button
[ HE.onClick $ HE.input_ NewRandom ]
[ HH.text $ show state.n ]
eval :: Query ~> H.ComponentDSL State Query e
eval (NewRandom next) = do
H.modify (\state -> state { n=12 } )
--I'd like to set n to a random number
--but I don't know how.
--let r = randomInt 1 10
--H.modify (\state -> state { n=r } )
pure next
main :: Eff (H.HalogenEffects ()) Unit
main =
runHalogenAff do
body <- awaitBody
H.runUI ui initialState body
You need to use an appropriate monad with your ComponentDSL
(where you have the e
type var currently) to make it possible, and then you can use H.fromEff
to lift the randomInt
:
module Main where
import Prelude
import Control.Monad.Aff (Aff)
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Random (randomInt, RANDOM)
import Halogen as H
import Halogen.HTML.Events.Indexed as HE
import Halogen.HTML.Indexed as HH
import Halogen.Util (runHalogenAff, awaitBody)
type State = { n::Int }
initialState :: State
initialState = { n: 3}
data Query a = NewRandom a
ui :: forall eff. H.Component { n :: Int } Query (Aff (random :: RANDOM | eff))
ui =
H.component { render, eval }
where
render :: State -> H.ComponentHTML Query
render state =
HH.button
[ HE.onClick $ HE.input_ NewRandom ]
[ HH.text $ show state.n ]
eval :: Query ~> H.ComponentDSL State Query (Aff (random :: RANDOM | eff))
eval (NewRandom next) = do
r <- H.fromEff $ randomInt 1 10
H.modify (\state -> state { n=r } )
pure next
main :: forall eff. Eff (H.HalogenEffects (random :: RANDOM | eff)) Unit
main =
runHalogenAff do
body <- awaitBody
H.runUI ui initialState body
(Aside: If you're doing effectful things, even if you only need Eff
, it's easiest to use Aff
as the ComponentDSL
monad, as when you use runUI
it expects it to be Aff
- it is possible to change the monad, using interpret
in the Halogen.Component
module, but since you'd just be using interpret liftAff
there anyway, you may as well go straight to Aff
.)
Take a look at the "Non-state effects" section of the guide, or the AJAX example for more details on running effects in eval
.