【问题标题】:purescript-halogen: modify state by effectful computationpurescript-halogen:通过有效计算修改状态
【发布时间】:2017-03-06 10:09:26
【问题描述】:

我想用一个依赖于旧状态的函数来修改我的状态,但也引入了一些随机性。我的函数f 看起来像这样:

f :: State -> Eff (random :: RANDOM) State

我想我的状态应该是纯的,我不知道如何摆脱Eff,除了使用unsafePerformEff,所以我这样做了:

eval :: Query ~> H.ComponentDSL State Query g
eval (Tick next) = do
  H.modify (unsafePerformEff <<< f)
  pure next

这可行,但必须有另一种更安全的方法。我已经在我的主函数中添加了随机效果:

main :: Eff (H.HalogenEffects (random :: RANDOM)) Unit

但是eval 应该是什么样子?可能modify在这里不行,还有别的更新状态的方法吗?

Purescript Halogen, side effect (random number) 对我不起作用,因为f 依赖于旧状态。

【问题讨论】:

  • 好的,我刚刚找到了 Halogen 的 getset,但仍然出现类型错误。

标签: purescript halogen


【解决方案1】:

modify 本身并不能让您执行有效的更新,但是是的,您可以使用get,然后使用modify(或set)来执行此操作。改编自另一个随机示例:

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
      state <- H.get
      nextState <- H.fromEff (nextRandom state)
      H.set nextState
      pure next

    nextRandom :: State -> Eff (random :: RANDOM | eff) State
    nextRandom { n } = do
      nextN <- randomInt (n + 1) (n + 10)
      pure { n: nextN }

main :: forall eff. Eff (H.HalogenEffects (random :: RANDOM | eff)) Unit
main =
    runHalogenAff do
    body <- awaitBody
    H.runUI ui initialState body

可能导致类型错误的是这种类型签名:

f :: State -> Eff (random :: RANDOM) State

效果行已关闭,这意味着它不会与任何其他行统一,您可能想要这样:

f :: forall eff. State -> Eff (random :: RANDOM | eff) State

【讨论】:

  • 我使用了封闭的效果行,因为我知道我的计算只涉及随机性,并且我想禁止任何其他效果。但显然这意味着我不能在“开放”的效果行中包含封闭的行?我还被要求明确注释(Aff (random :: RANDOM | eff)) 而不是任何g。谢谢,这使它编译!
  • 没错 - 如果您使用封闭行,那么您在整个程序中都会坚持使用它,因此它仅在顶层有用。使用开放行只允许注释表达式使用您在类型中提到的效果,但开放允许它稍后与其他有效表达式统一,容纳更多效果。是的,g 决定了应该使用什么类型来处理 Halogen 中的“非组件效应”,因此当未指定时,它不会承认任何有效的操作。
猜你喜欢
  • 2016-03-17
  • 2017-11-16
  • 2019-10-02
  • 1970-01-01
  • 2017-06-02
  • 2016-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多