Can I catch an Error and re-throw as a native EXCEPTION?

As part of my beginner’s project I’m decoding JSON that I read from a file. For readTextFile I’m in
Eff ( fs ∷ FS , exception ∷ EXCEPTION | eff ) anyway, but decodeJSON fails in ExceptT (NonEmptyList ForeignError). I can use runExcept and handle he cases with either, but I’m wondering if its possible to convert the Except into a native exception using catchError to handle the decoding error and re-throw it as an a native exception.

I had a go in the stacked monad:

readJson ::
  forall eff value.
    Decode value =>
    String ->
    ExceptT (NonEmptyList ForeignError) (Eff (fs :: FS, exception :: EXCEPTION |eff)) value
readJson fileName =
  do
     s <- lift $ readTextFile UTF8 fileName
     v <- rewrap (decodeJSON s) `catchError` rethrow s
     pure v
  where
      rewrap = mapExceptT (un Identity >>> pure)
      rethrow content e = lift $ throw $ "Couldn't decode JSON:" <> content

Is there a way to do this where I end up in Eff (fs: FS, exception: EXCEPTION |eff) without having to case on the error?

I can’t think off the top of my head of a way of ending up in Eff (fs :: FS, exception :: EXCEPTION | eff) without having to case on the error, no. I think part of the reason you’ll need to case on the error is that NonEmptyList ForeignError is different from a native JavaScript Error so you’ll have to do a little bit of work to turn the former into the latter (as you may have already realised).

Incidentally, I suspect the reason you didn’t get any responses for a while is that few people are using Eff these days; my impression is that most people are using Effect instead. (I’d recommend switching over if you haven’t come to that conclusion already yourself.)

1 Like