2017-02-15 1 views
1

L'exemple Purescript par l'article Exemple 8,17 État Mutable:Comment utiliser garde Eff monade

est une fonction Simuler:

import Prelude 

import Control.Monad.Eff (Eff, forE) 
import Control.Monad.ST (ST, newSTRef, readSTRef, modifySTRef) 

simulate :: forall eff h. Number -> Number -> Int -> Eff (st :: ST h | eff) Number 
simulate x0 v0 time = do 
    ref <- newSTRef { x: x0, v: v0 } 
    forE 0 (time * 1000) \_ -> do 
    modifySTRef ref \o -> 
     { v: o.v - 9.81 * 0.001 
     , x: o.x + o.v * 0.001 
     } 
    pure unit 
    final <- readSTRef ref 
    pure final.x 

La fonction elle-même fonctionne bien. Dites qu'il doit être modifié pour arrêter le mouvement de la particule à une valeur de x. Ce:

import Prelude 
import Control.MonadPlus (guard) 

import Control.Monad.Eff (Eff, forE) 
import Control.Monad.ST (ST, newSTRef, readSTRef, modifySTRef) 

simulate :: forall eff h. Number -> Number -> Int -> Eff (st :: ST h | eff) Number 
simulate x0 v0 time = do 
    ref <- newSTRef { x: x0, v: v0 } 
    forE 0 (time * 1000) \_ -> do 
    o <- readSTRef ref 
    let v = o.v - 9.81 * 0.001 
    let x = o.x + o.v * 0.001 
    guard (x < 100.0) 
    modifySTRef ref \o -> 
     { v: v 
     , x: x 
     } 
    pure unit 
    final <- readSTRef ref 
    pure final.x 

résultats dans l'erreur suivante:

No type class instance was found for 

    Control.MonadZero.MonadZero (Eff 
            ("st" :: ST h3 
            | eff4 
            ) 
           ) 
... 

Est-ce que cela signifie guard ne peut pas être utilisé dans Eff monade du tout? Comment écrirait-on le code avec la même intention dans un purescript idiomatique?

Répondre

2

Vous ne pouvez pas utiliser guard, mais vous pouvez utiliser when, qui fonctionne avec tout Monad:

when (x < 100.0) $ 
    modifySTRef ref \o -> 
    { v: v 
    , x: x 
    } 
+0

Génial, merci Phil! –

0

La fonction when ne fonctionne pas sur mon ordinateur, et ceci est ma solution.

_ <- modifySTRef ref (if cond then func else id)