Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Purescript Eff Monad and do blocks

I'm trying to understand why the following does not work in Purescript. I have a feeling it can also be answered by the Haskell community, thus I've cross listed it.

The general gist is:

If I have a do block, can I not throw in a disposable value? In this instance, I'm trying to log something (similar to Haskell's print) in the middle of a series of monadic computations.

main = do
    a <- someAction1
    b <- someAction2
    _ <- log "here is a statement I want printed"
    someAction3 a b

Specifically, I have a function which takes the following (from the Halogen example template project)

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

In my mind, this should work like in 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"

Specifically, the error that I get is type mismatch of the monads

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...

I know purescript makes me declare the "things I'm touching in the monad" (i.e. forall e. Eff ( a :: SOMEVAR, b :: SOMEOTHERVAR | eff ) Unit, but I'm not sure how to do that in this case...

like image 337
clo_jur Avatar asked Feb 06 '23 08:02

clo_jur


1 Answers

If you're working with version 0.12.0 of halogen you should be able to use fromEff from https://pursuit.purescript.org/packages/purescript-aff-free/3.0.0/docs/Control.Monad.Aff.Free#v:fromEff like so:

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

This is going to get a lot nicer in upcoming versions of halogen (>= 0.13) in which liftEff should be enough.

The reason for why you can't just use log right away, is that H.ComponentDSL is not a type synonym for Eff, but for Free and so you can't simply mix Eff and ComponentDSL actions.

like image 59
Christoph Hegemann Avatar answered Feb 16 '23 13:02

Christoph Hegemann