4
votes

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

1
If this is just for debugging purposes, you might be interested in using the Debug.Trace module from purescript-debug instead of dealing with propagating the effects everywhere, which is pretty burdensome for some temporary debug logging. You shouldn’t use that for anything but debugging, though, as the name would imply.Alexis King
@AlexisKing This isn't for debugging, as much as wanting to be able to quickly shoot off a message. Also, I'd like to know why it's not working for my own education.clo_jur
H.modify produces a Free .. .. while log produces a Eff .. .. - the error is telling you these are different types. You cannot use them in the same do block.user2407038

1 Answers

8
votes

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.