| Safe Haskell | Safe-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
- newtype EitherT e m a = EitherT {
- runEitherT :: m (Either e a)
- type Parser a = EitherT String (State String) a
- throwE :: String -> Parser a
- parseLetter :: Parser Char
- twoLettersM :: Parser (Char, Char)
- twoLettersA :: Parser (Char, Char)
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
| MonadTrans (EitherT e) Source # | Allows lifting actions from the inner monad into Here used to lift |
Defined in Lessons.Lesson15 | |
| Monad m => Applicative (EitherT e m) Source # | Applicative instance executes computations one by one and stops at the first error encountered. |
Defined in Lessons.Lesson15 | |
| Monad m => Functor (EitherT e m) Source # | Functor instance propagates errors and applies functions only to successful values. |
| Monad m => Monad (EitherT e m) Source # | Monad instance enables sequencing computations using |
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 parseLetterrunEitherT 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")