了解Purescript Eff Monad并做块

clo*_*jur 3 haskell purescript

我试图理解为什么以下在Purescript中不起作用.我有一种感觉,它也可以由Haskell社区回答,因此我已经交叉列出了它.

一般要点是:

如果我有do块,我可以不投入一次性价值吗?在这个例子中,我试图print在一系列monadic计算中记录某些东西(类似于Haskell的).

main = do
    a <- someAction1
    b <- someAction2
    _ <- log "here is a statement I want printed"
    someAction3 a b
Run Code Online (Sandbox Code Playgroud)

具体来说,我有一个功能,它采取以下(从卤素示例模板项目)

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
Run Code Online (Sandbox Code Playgroud)

在我看来,这应该像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"
Run Code Online (Sandbox Code Playgroud)

具体来说,我得到的错误是monad的类型不匹配

在尝试匹配类型与类型等时,无法将类型Eff与类型Free匹配...Eff ( "console" :: CONSOLE | t6 )Free (HalogenFP t0 { "isOn" :: t1 | t2 } t3 t4)

我知道purescript让我宣称"我在monad中触摸的东西"(即forall e. Eff ( a :: SOMEVAR, b :: SOMEOTHERVAR | eff ) Unit,但我不知道在这种情况下如何做到这一点......

Chr*_*ann 7

如果你正在使用的卤素0.12.0版本的工作,你应该能够使用fromEffhttps://pursuit.purescript.org/packages/purescript-aff-free/3.0.0/docs/Control.Monad.Aff.Free #v: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
Run Code Online (Sandbox Code Playgroud)

这将在即将推出的卤素版本(> = 0.13)中获得更好的效果,其中liftEff应该足够了.

你不能立即使用的原因log是,H.ComponentDSL它不是类型的同义词Eff,但是因为Free你不能简单地混合EffComponentDSL动作.

  • 你不能再保持`g`完全多态了.它用于携带整个程序中使用的效果.有关示例,请参阅https://github.com/slamdata/purescript-halogen/blob/v0.12.0/examples/ajax/src/Main.purs.你会想用`console :: CONSOLE`替换`ajax :: AJAX` (3认同)