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.