1
votes

I’m having a problem getting the following to compile:

module ContrivedExample where

import Prelude
import Data.Either (Either(..))
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Exception (EXCEPTION, throw)
import Control.Monad.Eff.Console (CONSOLE, log)
import Control.Monad.Eff.Class (liftEff)
import Control.Monad.Aff (launchAff)
import Control.Monad.Aff.Console (log) as A

contrivedExample :: forall e. Either String String -> Eff (exception :: EXCEPTION, console :: CONSOLE | e) Unit
contrivedExample a = do
       _ <- launchAff do
         _ <- A.log "yay"
         liftEff $ case a of
           Left e -> log e
           Right a -> throw a
       pure unit

I get this error:

Could not match type

    ( console :: CONSOLE
    | e3
    )

  with type

    ( exception :: EXCEPTION
    , console :: CONSOLE
    | t2
    )

If I remove exception from the Effect row, I get an error on the other side of the Either. Is there a better alternative to liftEff or some way I can unify the types?

1

1 Answers

1
votes

As per the documentation of launchAff:

Converts the asynchronous computation into a synchronous one. All values are ignored, and if the computation produces an error, it is thrown.

Catching exceptions by using catchException with the resulting Eff computation is not recommended, as exceptions may end up being thrown asynchronously, in which case they cannot be caught.

If you do need to handle exceptions, you can use runAff instead, or you can handle the exception within the Aff computation, using catchError (or any of the other mechanisms).

I believe you cannot throw exceptions inside launchAff, unless you also catch them inside the same computation. You can only carry out other effects inside the launchAff computation otherwise.