{- |
Copyright: (c) 2018-2020 Kowainik
SPDX-License-Identifier: MPL-2.0
Maintainer: Kowainik <xrom.xkov@gmail.com>

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 = (All -> Maybe Bool)
-> (Maybe Bool -> All) -> TomlCodec (Maybe Bool) -> TomlCodec All
forall b a. (b -> a) -> (a -> b) -> TomlCodec a -> TomlCodec b
dimap (Bool -> Maybe Bool
forall a. a -> Maybe a
Just (Bool -> Maybe Bool) -> (All -> Bool) -> All -> Maybe Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. All -> Bool
getAll) (All -> (Bool -> All) -> Maybe Bool -> All
forall b a. b -> (a -> b) -> Maybe a -> b
maybe All
forall a. Monoid a => a
mempty Bool -> All
All) (TomlCodec (Maybe Bool) -> TomlCodec All)
-> (Key -> TomlCodec (Maybe Bool)) -> Key -> TomlCodec All
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TomlCodec Bool -> TomlCodec (Maybe Bool)
forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional (TomlCodec Bool -> TomlCodec (Maybe Bool))
-> (Key -> TomlCodec Bool) -> Key -> TomlCodec (Maybe Bool)
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 = (Any -> Maybe Bool)
-> (Maybe Bool -> Any) -> TomlCodec (Maybe Bool) -> TomlCodec Any
forall b a. (b -> a) -> (a -> b) -> TomlCodec a -> TomlCodec b
dimap (Bool -> Maybe Bool
forall a. a -> Maybe a
Just (Bool -> Maybe Bool) -> (Any -> Bool) -> Any -> Maybe Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Any -> Bool
getAny) (Any -> (Bool -> Any) -> Maybe Bool -> Any
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Any
forall a. Monoid a => a
mempty Bool -> Any
Any) (TomlCodec (Maybe Bool) -> TomlCodec Any)
-> (Key -> TomlCodec (Maybe Bool)) -> Key -> TomlCodec Any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TomlCodec Bool -> TomlCodec (Maybe Bool)
forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional (TomlCodec Bool -> TomlCodec (Maybe Bool))
-> (Key -> TomlCodec Bool) -> Key -> TomlCodec (Maybe Bool)
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 :: (Key -> TomlCodec a) -> Key -> TomlCodec (Sum a)
sum codec :: Key -> TomlCodec a
codec = (Sum a -> Maybe a)
-> (Maybe a -> Sum a) -> TomlCodec (Maybe a) -> TomlCodec (Sum a)
forall b a. (b -> a) -> (a -> b) -> TomlCodec a -> TomlCodec b
dimap (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> (Sum a -> a) -> Sum a -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sum a -> a
forall a. Sum a -> a
getSum) (Sum a -> (a -> Sum a) -> Maybe a -> Sum a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Sum a
forall a. Monoid a => a
mempty a -> Sum a
forall a. a -> Sum a
Sum) (TomlCodec (Maybe a) -> TomlCodec (Sum a))
-> (Key -> TomlCodec (Maybe a)) -> Key -> TomlCodec (Sum a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TomlCodec a -> TomlCodec (Maybe a)
forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional (TomlCodec a -> TomlCodec (Maybe a))
-> (Key -> TomlCodec a) -> Key -> TomlCodec (Maybe a)
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 :: (Key -> TomlCodec a) -> Key -> TomlCodec (Product a)
product codec :: Key -> TomlCodec a
codec = (Product a -> Maybe a)
-> (Maybe a -> Product a)
-> TomlCodec (Maybe a)
-> TomlCodec (Product a)
forall b a. (b -> a) -> (a -> b) -> TomlCodec a -> TomlCodec b
dimap (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> (Product a -> a) -> Product a -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Product a -> a
forall a. Product a -> a
getProduct) (Product a -> (a -> Product a) -> Maybe a -> Product a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Product a
forall a. Monoid a => a
mempty a -> Product a
forall a. a -> Product a
Product) (TomlCodec (Maybe a) -> TomlCodec (Product a))
-> (Key -> TomlCodec (Maybe a)) -> Key -> TomlCodec (Product a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TomlCodec a -> TomlCodec (Maybe a)
forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional (TomlCodec a -> TomlCodec (Maybe a))
-> (Key -> TomlCodec a) -> Key -> TomlCodec (Maybe a)
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 :: (Key -> TomlCodec a) -> Key -> TomlCodec (First a)
first codec :: Key -> TomlCodec a
codec = TomlCodec (Maybe a) -> TomlCodec (First a)
forall b a. Coercible a b => TomlCodec a -> TomlCodec b
diwrap (TomlCodec (Maybe a) -> TomlCodec (First a))
-> (Key -> TomlCodec (Maybe a)) -> Key -> TomlCodec (First a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TomlCodec a -> TomlCodec (Maybe a)
forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional (TomlCodec a -> TomlCodec (Maybe a))
-> (Key -> TomlCodec a) -> Key -> TomlCodec (Maybe a)
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 :: (Key -> TomlCodec a) -> Key -> TomlCodec (Last a)
last codec :: Key -> TomlCodec a
codec = TomlCodec (Maybe a) -> TomlCodec (Last a)
forall b a. Coercible a b => TomlCodec a -> TomlCodec b
diwrap (TomlCodec (Maybe a) -> TomlCodec (Last a))
-> (Key -> TomlCodec (Maybe a)) -> Key -> TomlCodec (Last a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TomlCodec a -> TomlCodec (Maybe a)
forall a. TomlCodec a -> TomlCodec (Maybe a)
dioptional (TomlCodec a -> TomlCodec (Maybe a))
-> (Key -> TomlCodec a) -> Key -> TomlCodec (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> TomlCodec a
codec
{-# INLINE last #-}