-- |
-- Module      :  Data.IntermediateStructures1
-- Copyright   :  (c) Oleksandr Zhabenko 2019-2024
-- License     :  MIT
-- Maintainer  :  oleksandr.zhabenko@yahoo.com
--
-- Some simple functions to deal with transformations from structures to other ones, basically lists.
--
-- The function 'mapI' is taken from the [mmsyn5](https://hackage.haskell.org/package/mmsyn5) package. This inspired some more general functionality.

{-# LANGUAGE NoImplicitPrelude, BangPatterns #-}
{-# OPTIONS_HADDOCK -show-extensions #-}


module Data.IntermediateStructures1
 (
    -- * Operations to apply a function or two different functions to an element of the outer list (some of them create inner list)  
       mapI
       , map2I
    -- * Generalized construction functions for some other ones (generative functions)
       , inter
       , inter'
       , swapinter
       , swapinter'
  )
where

import GHC.Base
import GHC.List (concatMap)

-- | Function that applies additional function @f :: a -> [a]@ to @a@ if @p :: a -> Bool@ and @p a = True@
mapI :: (a -> Bool) -> (a -> [a]) -> [a] -> [a]
mapI :: forall a. (a -> Bool) -> (a -> [a]) -> [a] -> [a]
mapI a -> Bool
p a -> [a]
f = (a -> [a]) -> [a] -> [a]
forall a b. (a -> [b]) -> [a] -> [b]
concatMap (\a
x -> if a -> Bool
p a
x then a -> [a]
f a
x else [a
x])
{-# INLINE mapI #-}

-- | Function that applies additional function @f :: a -> [[a]]@ to @a@ if @p :: a -> Bool@ and @p a = True@
map2I :: (a -> Bool) -> (a -> [[a]]) -> [a] -> [a]
map2I :: forall a. (a -> Bool) -> (a -> [[a]]) -> [a] -> [a]
map2I a -> Bool
p a -> [[a]]
f = [[a]] -> [a]
forall a. Monoid a => [a] -> a
mconcat ([[a]] -> [a]) -> ([a] -> [[a]]) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> [[a]]) -> [a] -> [[a]]
forall a b. (a -> [b]) -> [a] -> [b]
concatMap (\a
x -> if a -> Bool
p a
x then a -> [[a]]
f a
x else [[a
x]])
{-# INLINE map2I #-}

-- | Some general transformation where the arguments that are not present are calculated from the one data argument @a@ being just present. Can be used to contstruct function @a -> d@ from some additional ideas.
inter :: (a -> b) -> (a -> c) -> (a -> b -> c -> d) -> a -> d
inter :: forall a b c d.
(a -> b) -> (a -> c) -> (a -> b -> c -> d) -> a -> d
inter a -> b
fb a -> c
fc a -> b -> c -> d
f3d a
x = a -> b -> c -> d
f3d a
x (a -> b
fb a
x) (a -> c
fc a
x) 
{-# INLINE inter #-}

-- | A variant of the 'inter' with swapped two first arguments. The following takes place:
-- > swapinter f g == inter g f
swapinter :: (a -> c) -> (a -> b) -> (a -> b -> c -> d) -> a -> d
swapinter :: forall a c b d.
(a -> c) -> (a -> b) -> (a -> b -> c -> d) -> a -> d
swapinter a -> c
fc a -> b
fb a -> b -> c -> d
f3d a
x = a -> b -> c -> d
f3d a
x (a -> b
fb a
x) (a -> c
fc a
x)
{-# INLINE swapinter #-}

-- | A variant of 'inter' with \'stricter\' calculation scheme. Can be in many cases more efficient.
inter' :: (a -> b) -> (a -> c) -> (a -> b -> c -> d) -> a -> d
inter' :: forall a b c d.
(a -> b) -> (a -> c) -> (a -> b -> c -> d) -> a -> d
inter' a -> b
fb a -> c
fc a -> b -> c -> d
f3d !a
x = a -> b -> c -> d
f3d a
x (a -> b
fb a
x) (a -> c
fc a
x) 
{-# INLINE inter' #-}

-- | A variant of the 'swapinter' with \'stricter\' calculation scheme. Can be in many cases more efficient.
swapinter' :: (a -> c) -> (a -> b) -> (a -> b -> c -> d) -> a -> d
swapinter' :: forall a c b d.
(a -> c) -> (a -> b) -> (a -> b -> c -> d) -> a -> d
swapinter' a -> c
fc a -> b
fb a -> b -> c -> d
f3d !a
x = a -> b -> c -> d
f3d a
x (a -> b
fb a
x) (a -> c
fc a
x)
{-# INLINE swapinter' #-}