如何在 Eff monad 中使用 guard
How to use guard in Eff monad
Purescript by Example 第 8.17 节可变状态中的示例:
是模拟函数:
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
函数本身运行良好。假设需要对其进行修改以在 x
的某个值处停止粒子的移动。这个:
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
导致以下错误:
No type class instance was found for
Control.MonadZero.MonadZero (Eff
( "st" :: ST h3
| eff4
)
)
...
这是否意味着 guard
根本不能在 Eff
monad 中使用?如何用惯用的纯脚本编写具有相同意图的代码?
您不能使用 guard
,但可以使用 when
,它适用于任何 Monad
:
when (x < 100.0) $
modifySTRef ref \o ->
{ v: v
, x: x
}
Purescript by Example 第 8.17 节可变状态中的示例:
是模拟函数:
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
函数本身运行良好。假设需要对其进行修改以在 x
的某个值处停止粒子的移动。这个:
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
导致以下错误:
No type class instance was found for
Control.MonadZero.MonadZero (Eff
( "st" :: ST h3
| eff4
)
)
...
这是否意味着 guard
根本不能在 Eff
monad 中使用?如何用惯用的纯脚本编写具有相同意图的代码?
您不能使用 guard
,但可以使用 when
,它适用于任何 Monad
:
when (x < 100.0) $
modifySTRef ref \o ->
{ v: v
, x: x
}