理解 Purescript Eff Monad 和 do 块
Understanding Purescript Eff Monad and do blocks
我想了解为什么以下内容在 Purescript 中不起作用。我觉得 Haskell 社区也可以回答这个问题,因此我交叉列出了它。
总的要点是:
如果我有一个do
块,我可以不扔一个一次性值吗?在这种情况下,我试图在一系列单子计算的中间记录一些东西(类似于 Haskell 的 print
)。
main = do
a <- someAction1
b <- someAction2
_ <- log "here is a statement I want printed"
someAction3 a b
具体来说,我有一个函数采用以下内容(来自 Halogen 示例模板项目)
data Query a = ToggleState a
eval :: Query ~> H.ComponentDSL State Query g
eval (Toggle next) = do
H.modify (\state -> state { isOn = not state.isOn })
_ <- log "updating the state!"
pure next
在我看来,这应该像 Haskell
中那样工作
barf :: IO Int
barf = do
_ <- print "Here I am!"
return 5
main :: IO ()
main = do
a <- barf
_ <- print $ "the value is: " ++ (show a)
print "done"
具体来说,我得到的错误是 monad 的类型不匹配
Could not match type Eff
with type Free
while trying to match type Eff ( "console" :: CONSOLE | t6 )
with type Free (HalogenFP t0 { "isOn" :: t1 | t2 } t3 t4)
... etc...
我知道 purescript 让我声明 "things I'm touching in the monad"(即 forall e. Eff ( a :: SOMEVAR, b :: SOMEOTHERVAR | eff ) Unit
,但我不确定在这种情况下该怎么做...
如果您使用的是 0.12.0 版的卤素,您应该能够像这样使用 https://pursuit.purescript.org/packages/purescript-aff-free/3.0.0/docs/Control.Monad.Aff.Free#v:fromEff 中的 fromEff
:
data Query a = ToggleState a
eval :: Query ~> H.ComponentDSL State Query g
eval (Toggle next) = do
H.modify (\state -> state { isOn = not state.isOn })
_ <- H.fromEff (log "updating the state!")
pure next
这在即将推出的卤素 (>= 0.13) 版本中会变得更好,其中 liftEff
应该足够了。
您不能立即使用 log
的原因是 H.ComponentDSL
不是 Eff
的类型同义词,而是 Free
和所以你不能简单地混合 Eff
和 ComponentDSL
动作。
我想了解为什么以下内容在 Purescript 中不起作用。我觉得 Haskell 社区也可以回答这个问题,因此我交叉列出了它。
总的要点是:
如果我有一个do
块,我可以不扔一个一次性值吗?在这种情况下,我试图在一系列单子计算的中间记录一些东西(类似于 Haskell 的 print
)。
main = do
a <- someAction1
b <- someAction2
_ <- log "here is a statement I want printed"
someAction3 a b
具体来说,我有一个函数采用以下内容(来自 Halogen 示例模板项目)
data Query a = ToggleState a
eval :: Query ~> H.ComponentDSL State Query g
eval (Toggle next) = do
H.modify (\state -> state { isOn = not state.isOn })
_ <- log "updating the state!"
pure next
在我看来,这应该像 Haskell
中那样工作barf :: IO Int
barf = do
_ <- print "Here I am!"
return 5
main :: IO ()
main = do
a <- barf
_ <- print $ "the value is: " ++ (show a)
print "done"
具体来说,我得到的错误是 monad 的类型不匹配
Could not match type
Eff
with typeFree
while trying to match typeEff ( "console" :: CONSOLE | t6 )
with typeFree (HalogenFP t0 { "isOn" :: t1 | t2 } t3 t4)
... etc...
我知道 purescript 让我声明 "things I'm touching in the monad"(即 forall e. Eff ( a :: SOMEVAR, b :: SOMEOTHERVAR | eff ) Unit
,但我不确定在这种情况下该怎么做...
如果您使用的是 0.12.0 版的卤素,您应该能够像这样使用 https://pursuit.purescript.org/packages/purescript-aff-free/3.0.0/docs/Control.Monad.Aff.Free#v:fromEff 中的 fromEff
:
data Query a = ToggleState a
eval :: Query ~> H.ComponentDSL State Query g
eval (Toggle next) = do
H.modify (\state -> state { isOn = not state.isOn })
_ <- H.fromEff (log "updating the state!")
pure next
这在即将推出的卤素 (>= 0.13) 版本中会变得更好,其中 liftEff
应该足够了。
您不能立即使用 log
的原因是 H.ComponentDSL
不是 Eff
的类型同义词,而是 Free
和所以你不能简单地混合 Eff
和 ComponentDSL
动作。