Panic in PureScript
Our example demonstrates how to handle unexpected errors or fail fast in situations that shouldn’t occur during normal operation. In PureScript, we use the Effect.Exception.throwException
function to achieve similar behavior.
module Main where
import Prelude
import Effect (Effect)
import Effect.Console (log)
import Effect.Exception (throwException, error)
import Node.FS.Sync (writeTextFile)
import Node.Encoding (Encoding(..))
main :: Effect Unit
main = do
-- We'll use throwException throughout this site to check for
-- unexpected errors. This is the only program on the
-- site designed to throw an exception.
throwException (error "a problem")
-- A common use of throwException is to abort if a function
-- returns an error value that we don't know how to
-- (or want to) handle. Here's an example of
-- throwing an exception if we get an unexpected error when creating a new file.
result <- try (writeTextFile UTF8 "/tmp/file" "")
case result of
Left err -> throwException err
Right _ -> pure unit
Running this program will cause it to throw an exception, print an error message, and exit with a non-zero status.
When the first throwException
in main
fires, the program exits without reaching the rest of the code. If you’d like to see the program try to create a temp file, comment out the first throwException
.
$ spago run
Error: a problem
CallStack (from HasCallStack):
error, called at src/Main.purs:12:3 in main:Main
Note that unlike some languages which use exceptions for handling of many errors, in PureScript it is idiomatic to use the Either
type or similar error-indicating return values wherever possible. The throwException
function should be used sparingly, primarily for truly exceptional situations.
In this example, we’ve used the try
function from the Control.Monad.Error.Class
module to catch and handle potential exceptions from file operations. This allows us to handle errors in a more functional way, using Either
to represent success or failure.
Remember that in PureScript, all side effects (including throwing exceptions) must be wrapped in the Effect
monad, which is why our main
function has the type Effect Unit
.