2016-10-24 5 views
1

Ich möchte meinen Zustand mit einer Funktion ändern, die vom alten Zustand abhängt, aber auch etwas Zufälligkeit einführt. Meine Funktion f sieht wie folgt aus:Purescript-Halogen: Zustand durch wirkungsvolle Berechnung ändern

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

Ich denke, mein Zustand rein sein sollte, und ich hatte keine Ahnung, wie Eff loszuwerden, andere als unsafePerformEff verwenden, also tat ich dies:

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

Das funktioniert, aber es muss einen anderen, sichereren Weg geben. Ich habe bereits den zufälligen Effekt auf meine Hauptfunktion:

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

Aber wie sollte eval aussehen? Vielleicht funktioniert modify hier nicht, und es gibt eine andere Möglichkeit, den Status zu aktualisieren?

Purescript Halogen, side effect (random number) funktioniert nicht für mich, seit f hängt vom alten Zustand ab.

+0

Okay, ich habe gerade Halogen 'Get' und' Set' gefunden, aber ich bekomme immer noch Typfehler. – stholzm

Antwort

1

modify selbst nicht lassen Sie effekt Updates durchführen, aber ja, können Sie get verwenden und dann modify (oder set) danach, dies zu tun. Übernommen aus dem anderen Beispiel mit zufälligen:

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 

Was auf den Typ Fehler führen könnte diese Art Unterschrift ist jedoch:

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

Die Wirkung Reihe geschlossen ist, das heißt, es wird nicht mit anderen vereinen Zeile, möchten Sie wahrscheinlich dies stattdessen:

+0

Ich benutzte eine geschlossene Reihe von Effekten, weil ich weiß, dass meine Berechnung nur Zufälligkeit beinhaltet und ich andere Effekte verbieten wollte. Aber das bedeutet offensichtlich, dass ich keine geschlossene Reihe in eine "offene" Reihe von Effekten einschließen kann? Ich wurde auch aufgefordert, '(Aff (random :: RANDOM | eff))' explizit zu kommentieren anstatt nur irgendein 'g'. Danke, das hat es kompiliert! – stholzm

+1

Das ist richtig - wenn du eine geschlossene Reihe benutzt hast, dann bist du für das gesamte Programm dran, also ist es nur auf der obersten Ebene nützlich. Wenn Sie eine offene Zeile verwenden, können Sie nur den mit Anmerkungen versehenen Ausdruck mit den Effekten verwenden, die Sie in diesem Typ erwähnen, aber wenn er geöffnet ist, kann er später mit anderen effektvollen Ausdrücken vereinheitlicht werden und mehr Effekte aufnehmen. Und yep, 'g' bestimmt, welcher Typ verwendet werden soll, um" Nicht-Komponenteneffekte "in Halogen zu behandeln, so dass, wenn es nicht spezifiziert wird, keine wirksamen Operationen zugelassen werden. –

Verwandte Themen