kdl-hs-1.1.1: KDL language parser and API
Safe HaskellNone
LanguageGHC2021

KDL.Applicative

Description

This module is intended to be imported qualified as:

import KDL.Applicative qualified as KDL

This module is equivalent to KDL, except when ApplicativeDo and QualifiedDo are enabled, KDL.do will ensure you don't accidentally use monadic operations.

The Applicative decoder can do most of the things the Arrow decoder can do, except run different decoders based on a previously decoded result. If you need to do that, either use KDL.Arrow, or follow this example:

# Example KDL config

rules {
  - a
  - b {
    foo 123 # only allowed in b, not a
  }
}
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE QualifiedDo #-}

import KDL.Arrow ((>>>), (|||))
import KDL.Arrow qualified

decoder = KDL.do
  rules <-
    KDL.dashNodesWith "rules" $
      (toEither <$> KDL.arg) >>> fromEither
  pure rules
 where
  toEither = case
    "a" -> Left $ ()
    "b" -> Right . Left $ ()
    name -> Right . Right $ "Invalid rule: " <> name
  fromEither =
    -- "a"
    pure RuleA |||
    -- "b"
    (RuleB <$> KDL.children (KDL.argAt "foo")) |||
    -- else
    KDL.Arrow.fail
Synopsis

QualifiedDo

fmap :: Functor f => (a -> b) -> f a -> f b #

fmap is used to apply a function of type (a -> b) to a value of type f a, where f is a functor, to produce a value of type f b. Note that for any type constructor with more than one parameter (e.g., Either), only the last type parameter can be modified with fmap (e.g., b in `Either a b`).

Some type constructors with two parameters or more have a Bifunctor instance that allows both the last and the penultimate parameters to be mapped over.

Examples

Expand

Convert from a Maybe Int to a Maybe String using show:

>>> fmap show Nothing
Nothing
>>> fmap show (Just 3)
Just "3"

Convert from an Either Int Int to an Either Int String using show:

>>> fmap show (Left 17)
Left 17
>>> fmap show (Right 17)
Right "17"

Double each element of a list:

>>> fmap (*2) [1,2,3]
[2,4,6]

Apply even to the second element of a pair:

>>> fmap even (2,2)
(2,True)

It may seem surprising that the function is only applied to the last element of the tuple compared to the list example above which applies it to every element in the list. To understand, remember that tuples are type constructors with multiple type parameters: a tuple of 3 elements (a,b,c) can also be written (,,) a b c and its Functor instance is defined for Functor ((,,) a b) (i.e., only the third parameter is free to be mapped over with fmap).

It explains why fmap can be used with tuples containing values of different types as in the following example:

>>> fmap even ("hello", 1.0, 4)
("hello",1.0,True)

pure :: Applicative f => a -> f a #

Lift a value.

return :: Monad m => a -> m a #

Inject a value into the monadic type.

(<*>) :: Applicative f => f (a -> b) -> f a -> f b infixl 4 #

Sequential application.

A few functors support an implementation of <*> that is more efficient than the default one.

Example

Expand

Used in combination with (<$>), (<*>) can be used to build a record.

>>> data MyState = MyState {arg1 :: Foo, arg2 :: Bar, arg3 :: Baz}
>>> produceFoo :: Applicative f => f Foo
>>> produceBar :: Applicative f => f Bar
>>> produceBaz :: Applicative f => f Baz
>>> mkState :: Applicative f => f MyState
>>> mkState = MyState <$> produceFoo <*> produceBar <*> produceBaz

(>>) :: Monad m => m a -> m b -> m b infixl 1 #

Sequentially compose two actions, discarding any value produced by the first, like sequencing operators (such as the semicolon) in imperative languages.

'as >> bs' can be understood as the do expression

do as
   bs

(>>=) :: NoBind a => a Source #

Gives a compile-time error if used.

It seems like QualifiedDo still needs a definition for this, even with ApplicativeDo enabled. https://gitlab.haskell.org/ghc/ghc/-/issues/26723

Re-exports

module KDL.Parser

module KDL.Render

module KDL.Types