PureScript by Example, in the section The Eff Monad -> Handlers and Actions states that "[an effect] handler usually subtracts effects from the set". However, the examples are rather opaque and I can't work out how to write my own handler to achieve this.
Specifically, I'm working with purescript-aff and purescript-affjax. I'd like to use runAff (from purescript-aff) in combination with get (from purescript-affjax).
The problem is that get
uses the Affjax monad, whereas runAff
expects something using the Aff monad.
Affjax is defined as:
type Affjax e a = Aff (ajax :: AJAX | e) (AffjaxResponse a)
Aff is defined as:
foreign import data Aff :: # ! -> * -> *
I, therefore, want to write a function that has the following type:
Affjax e a -> Aff e a
This seems to me to require a handler that subtracts the ajax
part of the effect set. How would one code such a handler?
Attempting to pattern-match, as below, of course results in the error unexpected |
.
handleAffjax :: Affjax e a -> Aff e a
handleAffjax (Aff ( | eff1 ) resp1) = Aff eff1 resp1
Thanks all.
Update
Inspired by @christoph-hegemann's answer below, I was able to track down most of the issues with my code.
I think the answer to the question in the title is that one does not subtract an effect from the set, and that description is a little confusing. The effect remains after you've handled it.
The intuition I was missing is that I have to add the expected effects to the calling function type. The lack of a type declaration on main
hid that to some extent. I worked it out when I turned Christoph's example into the following compiling example:
module Main where
import Debug.Trace
import Network.HTTP.Affjax
import Control.Monad.Aff
import Control.Monad.Eff
import Control.Monad.Eff.Exception
initialUrl :: URL
initialUrl = "http://127.0.0.1:8000/api/v1/navitem/2/"
runGet :: forall e. Eff (ajax :: AJAX, trace :: Trace | e) Unit
runGet = runAff errorHandler successHandler (get initialUrl)
errorHandler :: forall e. Error -> Eff (trace :: Trace | e) Unit
errorHandler err = print err
successHandler :: forall e. AffjaxResponse String -> Eff (trace :: Trace | e) Unit
successHandler res = print res.response
main = runGet