liveBook · Manning

Either

As explained in Learn Haskell by Example

Either is a parameterized Haskell type representing a value with one of two alternatives, conventionally an error value or a successful result.

Either is a parameterized Haskell type for a result with two alternatives: `Left a` or `Right b`. It commonly represents an operation that can fail while preserving an explanation of the failure: `Left` holds an error and `Right` holds the successful value. Unlike `Maybe`, it does not discard why a result was unavailable. section 7.2.1 section 7.5

A useful shape is `Either String Csv`: a CSV constructor can return a descriptive message when its inputs violate table invariants, or a completed `Csv` when they are valid. This keeps validation visible in the result type instead of silently failing or immediately crashing. section 7.2.1

Listing 7.5 An unsafe function that crashes if the arguments for a CSV value are invalid
unsafeMkCsv :: Maybe [T.Text] -> [Column] -> Csv
unsafeMkCsv header columns =
  E.either error id (mkCsv header columns)  #1

This unsafe wrapper consumes the checked result with `either`: it crashes on `Left` through `error`, or returns the `Right` value unchanged through `id`. Keep the safe constructor when invalid input can still occur. section 7.2.2

Use Either where a failure needs a value of its own:

  • Validate data at construction time. `mkCsv` checks header and column sizes, returning `Left` messages for invalid tables and `Right Csv` for valid ones. section 7.2.1 section 7.2.2
  • Make parsing failures explicit. A parser can return `Either ErrorMessage a`, allowing an unmatched PNM magic number to produce a message rather than a crash. section 12.1.2
  • Carry both unconsumed input and a parsed value on success. `ParseResult a` uses `Either ErrorMessage (Text, a)` so later parsers can receive the remaining input. section 12.1.2
  • Turn selected IO exceptions into returned results. `try` can produce `IO (Either IOException a)`, placing filesystem or network exceptions in `Left` while leaving successful values in `Right`. section 14.4

`either` eliminates an Either by accepting one function for `Left` and another for `Right`, both producing the same final type. It is convenient when both outcomes must be handled immediately, but converting a recoverable `Left` into `error` creates an intentionally unsafe boundary. section 7.2.2

Checking a CSV table

Given two header fields and two equally sized columns, `mkCsv` returns `Right Csv`. A shorter column returns `Left "The columns do not have equal sizes"`; a one-field header for two columns returns `Left "Size of header row does not fit number of columns"`. The caller can inspect those outcomes rather than receive an exception. section 7.2.2

Either also works with `fmap`: mapping over `Right 1` can produce `Right 2`, while mapping over `Left 1` leaves the failure unchanged. This lets parser transformations change successful parsed values without replacing their error path. section 12.1.2

How Learn Haskell by Example covers it

How deep it goes
Defines Left and Right, applies them in smart constructors and parsers, and demonstrates elimination with either and mapping with fmap.
Examples
Demonstrates CSV size checks, PNM magic-number parsing, fixed-string parsers, and safe filesystem listing.
What it assumes
Introduces error-carrying results by contrasting Maybe, while using Haskell functions, type signatures, records, and pattern matching.
What you can do after
Apply it via Data.Either and Control.Exception to return recoverable errors instead of silently failing or crashing.
How it connects
Connects Maybe, smart constructors, error, parsers, Functor, IO, and exceptions through explicit success and failure results.

Also explained in

Compare how 4 books explain Either →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.