Safe HaskellSafe-Inferred

Lessons.Lesson15

Description

Notes taken by Lukas Zujevas

This lesson introduces a simple parser built using monad transformers. The goal is to combine:

  • 'State String' for input consumption
  • 'Either String' for error reporting

via the EitherT transformer.

This demonstrates how multiple effects can be composed into a single monad.

Synopsis

Documentation

newtype EitherT e m a Source #

A monad transformer that adds error handling to an existing monad

EitherT e m a represents a computation in monad m that can either:

  • succeed with a value of type a
  • fail with an error of type e

Internally, this is just a wrapper around m (Either e a)

Constructors

EitherT 

Fields

Instances

Instances details
MonadTrans (EitherT e) Source #

Allows lifting actions from the inner monad into EitherT.

Here used to lift State operations.

Instance details

Defined in Lessons.Lesson15

Methods

lift :: Monad m => m a -> EitherT e m a

Monad m => Applicative (EitherT e m) Source #

Applicative instance executes computations one by one and stops at the first error encountered.

Instance details

Defined in Lessons.Lesson15

Methods

pure :: a -> EitherT e m a

(<*>) :: EitherT e m (a -> b) -> EitherT e m a -> EitherT e m b

liftA2 :: (a -> b -> c) -> EitherT e m a -> EitherT e m b -> EitherT e m c

(*>) :: EitherT e m a -> EitherT e m b -> EitherT e m b

(<*) :: EitherT e m a -> EitherT e m b -> EitherT e m a

Monad m => Functor (EitherT e m) Source #

Functor instance propagates errors and applies functions only to successful values.

Instance details

Defined in Lessons.Lesson15

Methods

fmap :: (a -> b) -> EitherT e m a -> EitherT e m b

(<$) :: a -> EitherT e m b -> EitherT e m a

Monad m => Monad (EitherT e m) Source #

Monad instance enables sequencing computations using do-notation. Errors short-circuit the computation.

Instance details

Defined in Lessons.Lesson15

Methods

(>>=) :: EitherT e m a -> (a -> EitherT e m b) -> EitherT e m b

(>>) :: EitherT e m a -> EitherT e m b -> EitherT e m b

return :: a -> EitherT e m a

type Parser a = EitherT String (State String) a Source #

A simple parser type.

  • 'State String' stores the remaining input
  • 'Either String' represents parsing failure

Running a parser produces a result and the leftover input.

throwE :: String -> Parser a Source #

Immediately fail with an error message.

The parser state is not modified.

parseLetter :: Parser Char Source #

Parse a single alphabetic character.

Rules:

  • If input is empty, parsing fails.
  • If the first character is alphabetic, it is consumed and returned.
  • Otherwise, parsing fails without consuming input.

Examples:

>>> :t runEitherT parseLetter
runEitherT parseLetter :: State String (Either String Char)
>>> :t runState (runEitherT parseLetter)
runState (runEitherT parseLetter) :: String -> (Either String Char, String)
>>> runState (runEitherT parseLetter) ""
(Left "A letter is expected but got empty input","")
>>> runState (runEitherT parseLetter) "13123"
(Left "A letter is expected, but got 1","13123")
>>> runState (runEitherT parseLetter) "abba"
(Right 'a',"bba")

twoLettersM :: Parser (Char, Char) Source #

Parse two letters sequentially using monadic composition.

Example:

>>> runState (runEitherT twoLettersM) "abba"
(Right ('a','b'),"ba")

twoLettersA :: Parser (Char, Char) Source #

Parse two letters using Applicative composition.

Equivalent to twoLettersM, but expressed without explicit binding.

Example:

>>> runState (runEitherT twoLettersA) "abba"
(Right ('a','b'),"ba")