Purescript Halogen, side effect (random number)

ぃ、小莉子 提交于 2019-12-11 04:46:15

问题


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

回答1:


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.



来源:https://stackoverflow.com/questions/39788618/purescript-halogen-side-effect-random-number

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!