Blame Options/Applicative/Arrows.hs

Packit 3fa651
-- | This module contains an arrow interface for option parsers, which allows
Packit 3fa651
-- to define and combine parsers using the arrow notation and arrow
Packit 3fa651
-- combinators.
Packit 3fa651
--
Packit 3fa651
-- The arrow syntax is particularly useful to create parsers of nested
Packit 3fa651
-- structures, or records where the order of fields is different from the order
Packit 3fa651
-- in which the parsers should be applied.
Packit 3fa651
--
Packit 3fa651
-- For example, an 'Options.Applicative.Builder.arguments` parser often needs
Packit 3fa651
-- to be applied last, and that makes it inconvenient to use it for a field
Packit 3fa651
-- which is not the last one in a record.
Packit 3fa651
--
Packit 3fa651
-- Using the arrow syntax and the functions in this module, one can write, e.g.:
Packit 3fa651
--
Packit 3fa651
-- > data Options = Options
Packit 3fa651
-- >   { optArgs :: [String]
Packit 3fa651
-- >   , optVerbose :: Bool }
Packit 3fa651
-- >
Packit 3fa651
-- > opts :: Parser Options
Packit 3fa651
-- > opts = runA $ proc () -> do
Packit 3fa651
-- >   verbose <- asA (switch (short 'v')) -< ()
Packit 3fa651
-- >   args <- asA (arguments str idm) -< ()
Packit 3fa651
-- >   returnA -< Options args verbose
Packit 3fa651
--
Packit 3fa651
-- Parser arrows, created out of regular 'Parser' values using the 'asA'
Packit 3fa651
-- function, are arrows taking @()@ as argument and returning the parsed value.
Packit 3fa651
module Options.Applicative.Arrows (
Packit 3fa651
  module Control.Arrow,
Packit 3fa651
  A(..),
Packit 3fa651
  asA,
Packit 3fa651
  runA,
Packit 3fa651
  ParserA,
Packit 3fa651
  ) where
Packit 3fa651
Packit 3fa651
import Control.Arrow
Packit 3fa651
import Control.Category (Category(..))
Packit 3fa651
Packit 3fa651
import Options.Applicative
Packit 3fa651
Packit 3fa651
import Prelude hiding ((.), id)
Packit 3fa651
Packit 3fa651
-- | For any 'Applicative' functor @f@, @A f@ is the 'Arrow' instance
Packit 3fa651
-- associated to @f@.
Packit 3fa651
--
Packit 3fa651
-- The 'A' constructor can be used to convert a value of type @f (a -> b)@ into
Packit 3fa651
-- an arrow.
Packit 3fa651
newtype A f a b = A
Packit 3fa651
  { unA :: f (a -> b) }
Packit 3fa651
Packit 3fa651
-- | Convert a value of type @f a@ into an arrow taking @()@ as argument.
Packit 3fa651
--
Packit 3fa651
-- Applied to a value of type 'Parser', it turns it into an arrow that can be
Packit 3fa651
-- used inside an arrow command, or passed to arrow combinators.
Packit 3fa651
asA :: Applicative f => f a -> A f () a
Packit 3fa651
asA x = A $ const <$> x
Packit 3fa651
Packit 3fa651
-- | Convert an arrow back to an applicative value.
Packit 3fa651
--
Packit 3fa651
-- This function can be used to return a result of type 'Parser' from an arrow
Packit 3fa651
-- command.
Packit 3fa651
runA :: Applicative f => A f () a -> f a
Packit 3fa651
runA a = unA a <*> pure ()
Packit 3fa651
Packit 3fa651
instance Applicative f => Category (A f) where
Packit 3fa651
  id = A $ pure id
Packit 3fa651
  -- use reverse composition, because we want effects to run from
Packit 3fa651
  -- top to bottom in the arrow syntax
Packit 3fa651
  (A f) . (A g) = A $ flip (.) <$> g <*> f
Packit 3fa651
Packit 3fa651
instance Applicative f => Arrow (A f) where
Packit 3fa651
  arr = A . pure
Packit 3fa651
  first (A f) = A $ first <$> f
Packit 3fa651
Packit 3fa651
-- | The type of arrows associated to the applicative 'Parser' functor.
Packit 3fa651
type ParserA = A Parser