{- |
Module                  : Toml.Codec.Combinator.Monoid
Copyright               : (c) 2018-2022 Kowainik
SPDX-License-Identifier : MPL-2.0
Maintainer              : Kowainik <xrom.xkov@gmail.com>
Stability               : Stable
Portability             : Portable

TOML-specific combinators for converting between TOML and Haskell 'Monoid'
wrapper data types. These codecs are especially handy when you are implementing
the [Partial Options Monoid](https://medium.com/@jonathangfischoff/the-partial-options-monoid-pattern-31914a71fc67)
pattern.

+-----------------------+------------+----------------------------+---------------------+
|     Haskell Type      |   @TOML@   |        'TomlCodec'         | Default on          |
|                       |            |                            | missing field       |
+=======================+============+============================+=====================+
| __'All'__             | @a = true@ | @'all' "a"@                | @'All' 'True'@      |
+-----------------------+------------+----------------------------+---------------------+
| __'Any'__             | @a = true@ | @'any' "a"@                | @'Any' 'False'@     |
+-----------------------+------------+----------------------------+---------------------+
| __@'Sum' 'Int'@__     | @a = 11@   | @'sum' 'Toml.int' "a"@     | @'Sum' 0@           |
+-----------------------+------------+----------------------------+---------------------+
| __@'Product' 'Int'@__ | @a = 11@   | @'product' 'Toml.int' "a"@ | @'Product' 1@       |
+-----------------------+------------+----------------------------+---------------------+
| __@'First' 'Int'@__   | @a = 42@   | @'first' 'Toml.int' "a"@   | @'First' 'Nothing'@ |
+-----------------------+------------+----------------------------+---------------------+
| __@'Last' 'Bool'@__   | @a = true@ | @'last' 'Toml.bool' "a"@   | @'Last' 'Nothing'@  |
+-----------------------+------------+----------------------------+---------------------+

@since 1.3.0.0
-}

module Toml.Codec.Combinator.Monoid
    ( -- * Codecs for 'Monoid's
      -- ** Bool wrappers
      all
    , any
      -- ** 'Num' wrappers
    , sum
    , product
      -- ** 'Maybe' wrappers
    , first
    , last
    ) where

import Prelude hiding (all, any, last, product, sum)

import Data.Monoid (All (..), Any (..), First (..), Last (..), Product (..), Sum (..))

import Toml.Codec.Combinator.Primitive (bool)
import Toml.Codec.Di (dimap, dioptional, diwrap)
import Toml.Codec.Types (TomlCodec)
import Toml.Type.Key (Key)


{- | Codec for 'All' wrapper for boolean values.
Returns @'All' 'True'@ on missing fields.

Decodes to @'All' 'True'@ when the key is not present.

@since 1.2.1.0
-}
all :: Key -> TomlCodec All
all :: Key -> TomlCodec All
all = forall b a. (b -> a) -> (a -> b) -> TomlCodec a -> TomlCodec b
dimap (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. All -> Bool
getAll) (forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. Monoid a => a
mempty Bool -> All
All) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> TomlCodec Bool
bool
{-# INLINE all #-}

{- | Codec for 'Any' wrapper for boolean values.
Returns @'Any' 'False'@ on missing fields.

Decodes to @'Any' 'False'@ when the key is not present.

@since 1.2.1.0
-}
any :: Key -> TomlCodec Any
any :: Key -> TomlCodec Any
any = forall b a. (b -> a) -> (a -> b) -> TomlCodec a -> TomlCodec b
dimap (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. Any -> Bool
getAny) (forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. Monoid a => a
mempty Bool -> Any
Any) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> TomlCodec Bool
bool
{-# INLINE any #-}

{- | Codec for 'Sum' wrapper for given converter's values.

Decodes to @'Sum' 0@ when the key is not present.

@since 1.2.1.0
-}
sum :: (Num a) => (Key -> TomlCodec a) -> Key -> TomlCodec (Sum a)
sum :: forall a. Num a => (Key -> TomlCodec a) -> Key -> TomlCodec (Sum a)
sum Key -> TomlCodec a
codec = forall b a. (b -> a) -> (a -> b) -> TomlCodec a -> TomlCodec b
dimap (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Sum a -> a
getSum) (forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. Monoid a => a
mempty forall a. a -> Sum a
Sum) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> TomlCodec a
codec
{-# INLINE sum #-}

{- | Codec for 'Product' wrapper for given converter's values.

Decodes to @'Product' 1@ when the key is not present.

@since 1.2.1.0
-}
product :: (Num a) => (Key -> TomlCodec a) -> Key -> TomlCodec (Product a)
product :: forall a.
Num a =>
(Key -> TomlCodec a) -> Key -> TomlCodec (Product a)
product Key -> TomlCodec a
codec = forall b a. (b -> a) -> (a -> b) -> TomlCodec a -> TomlCodec b
dimap (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Product a -> a
getProduct) (forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. Monoid a => a
mempty forall a. a -> Product a
Product) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> TomlCodec a
codec
{-# INLINE product #-}

{- | Codec for 'First' wrapper for given converter's values.

Decodes to @'First' 'Nothing'@ when the key is not present.

@since 1.2.1.0
-}
first :: (Key -> TomlCodec a) -> Key -> TomlCodec (First a)
first :: forall a. (Key -> TomlCodec a) -> Key -> TomlCodec (First a)
first Key -> TomlCodec a
codec = forall b a. Coercible a b => TomlCodec a -> TomlCodec b
diwrap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> TomlCodec a
codec
{-# INLINE first #-}

{- | Codec for 'Last' wrapper for given converter's values.

Decodes to @'Last' 'Nothing'@ when the key is not present.

@since 1.2.1.0
-}
last :: (Key -> TomlCodec a) -> Key -> TomlCodec (Last a)
last :: forall a. (Key -> TomlCodec a) -> Key -> TomlCodec (Last a)
last Key -> TomlCodec a
codec = forall b a. Coercible a b => TomlCodec a -> TomlCodec b
diwrap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> TomlCodec a
codec
{-# INLINE last #-}