{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ConstraintKinds, FlexibleContexts #-}
{-# LANGUAGE DataKinds, KindSignatures, TypeOperators #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Data.OneOrMoreApp (
	-- * Type
	OneOrMoreApp,
	-- * Constraint Synonym
	Expandable, Collapsable, Mergeable,
	-- * Function
	-- ** Single Type
	pattern Singleton, unSingleton,
	-- ** Multiple Type
	project, (>-),
	-- ** Expand and Collapse
	expand, collapse,
	-- ** Merge
	merge, merge' ) where

import Data.Kind
import Data.Type.Set.Internal
import Data.Type.SetApp.Internal
import qualified Data.OneOrMore.Internal as Oom

data OneOrMoreApp :: SetApp Type -> Type where
	OneOrMoreApp ::  Oom.OneOrMore as ->  OneOrMoreApp ('SetApp f as)

{-# COMPLETE Singleton #-}

pattern Singleton :: a -> OneOrMoreApp ('SetApp f (Singleton a))
pattern $bSingleton :: forall a (f :: * -> *). a -> OneOrMoreApp ('SetApp f (Singleton a))
$mSingleton :: forall {r} {a} {f :: * -> *}.
OneOrMoreApp ('SetApp f (Singleton a))
-> (a -> r) -> ((# #) -> r) -> r
Singleton x = OneOrMoreApp (Oom.Singleton x)

unSingleton :: OneOrMoreApp ('SetApp f (Singleton a)) -> a
unSingleton :: forall (f :: * -> *) a. OneOrMoreApp ('SetApp f (Singleton a)) -> a
unSingleton (Singleton a
x) = a
x

expand :: Oom.Expandable as as' => OneOrMoreApp ('SetApp f as) -> OneOrMoreApp ('SetApp f as')
expand :: forall (as :: Set (*)) (as' :: Set (*)) (f :: * -> *).
Expandable as as' =>
OneOrMoreApp ('SetApp f as) -> OneOrMoreApp ('SetApp f as')
expand (OneOrMoreApp OneOrMore as
xs) = forall (as :: Set (*)) (f :: * -> *).
OneOrMore as -> OneOrMoreApp ('SetApp f as)
OneOrMoreApp forall a b. (a -> b) -> a -> b
$ forall (as :: Set (*)) (as' :: Set (*)).
Expandable as as' =>
OneOrMore as -> OneOrMore as'
Oom.expand OneOrMore as
xs

collapse :: Oom.Collapsable as as' => OneOrMoreApp ('SetApp f as) -> Maybe (OneOrMoreApp ('SetApp f as'))
collapse :: forall (as :: Set (*)) (as' :: Set (*)) (f :: * -> *).
Collapsable as as' =>
OneOrMoreApp ('SetApp f as) -> Maybe (OneOrMoreApp ('SetApp f as'))
collapse (OneOrMoreApp OneOrMore as
xs) = forall (as :: Set (*)) (f :: * -> *).
OneOrMore as -> OneOrMoreApp ('SetApp f as)
OneOrMoreApp forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (as :: Set (*)) (as' :: Set (*)).
Collapsable as as' =>
OneOrMore as -> Maybe (OneOrMore as')
Oom.collapse OneOrMore as
xs

project :: Oom.Projectable as a => OneOrMoreApp ('SetApp f as) -> Maybe a
project :: forall (as :: Set (*)) a (f :: * -> *).
Projectable as a =>
OneOrMoreApp ('SetApp f as) -> Maybe a
project (OneOrMoreApp OneOrMore as
xs) = forall (as :: Set (*)) a.
Projectable as a =>
OneOrMore as -> Maybe a
Oom.project OneOrMore as
xs

(>-) :: Oom.Insertable a as as' => a -> OneOrMoreApp ('SetApp f as) -> OneOrMoreApp ('SetApp f as')
a
x >- :: forall a (as :: Set (*)) (as' :: Set (*)) (f :: * -> *).
Insertable a as as' =>
a -> OneOrMoreApp ('SetApp f as) -> OneOrMoreApp ('SetApp f as')
>- (OneOrMoreApp OneOrMore as
xs) = forall (as :: Set (*)) (f :: * -> *).
OneOrMore as -> OneOrMoreApp ('SetApp f as)
OneOrMoreApp forall a b. (a -> b) -> a -> b
$ a
x forall a (as :: Set (*)) (as' :: Set (*)).
Insertable a as as' =>
a -> OneOrMore as -> OneOrMore as'
Oom.>-. OneOrMore as
xs

merge :: Oom.Mergeable as as' mrg => OneOrMoreApp ('SetApp f as) -> OneOrMoreApp ('SetApp f as') -> OneOrMoreApp ('SetApp f mrg)
OneOrMoreApp OneOrMore as
xs merge :: forall (as :: Set (*)) (as' :: Set (*)) (mrg :: Set (*))
       (f :: * -> *).
Mergeable as as' mrg =>
OneOrMoreApp ('SetApp f as)
-> OneOrMoreApp ('SetApp f as') -> OneOrMoreApp ('SetApp f mrg)
`merge` OneOrMoreApp OneOrMore as
xs' = forall (as :: Set (*)) (f :: * -> *).
OneOrMore as -> OneOrMoreApp ('SetApp f as)
OneOrMoreApp forall a b. (a -> b) -> a -> b
$ OneOrMore as
xs forall (as :: Set (*)) (as' :: Set (*)) (mrg :: Set (*)).
Mergeable as as' mrg =>
OneOrMore as -> OneOrMore as' -> OneOrMore mrg
`Oom.merge_` OneOrMore as
xs'

unOneOrMoreApp :: OneOrMoreApp ('SetApp f as) -> Oom.OneOrMore as
unOneOrMoreApp :: forall (f :: * -> *) (as :: Set (*)).
OneOrMoreApp ('SetApp f as) -> OneOrMore as
unOneOrMoreApp (OneOrMoreApp OneOrMore as
xs) = OneOrMore as
xs

merge' :: (Oom.Mergeable as as' mrg, Oom.Expandable as mrg, Oom.Expandable as' mrg) =>
	Maybe (OneOrMoreApp ('SetApp f as)) -> Maybe (OneOrMoreApp ('SetApp f as')) -> Maybe (OneOrMoreApp ('SetApp f mrg))
Maybe (OneOrMoreApp ('SetApp f as))
xs merge' :: forall (as :: Set (*)) (as' :: Set (*)) (mrg :: Set (*))
       (f :: * -> *).
(Mergeable as as' mrg, Expandable as mrg, Expandable as' mrg) =>
Maybe (OneOrMoreApp ('SetApp f as))
-> Maybe (OneOrMoreApp ('SetApp f as'))
-> Maybe (OneOrMoreApp ('SetApp f mrg))
`merge'` Maybe (OneOrMoreApp ('SetApp f as'))
xs' = forall (as :: Set (*)) (f :: * -> *).
OneOrMore as -> OneOrMoreApp ('SetApp f as)
OneOrMoreApp forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall (f :: * -> *) (as :: Set (*)).
OneOrMoreApp ('SetApp f as) -> OneOrMore as
unOneOrMoreApp forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (OneOrMoreApp ('SetApp f as))
xs) forall (as :: Set (*)) (as' :: Set (*)) (mrg :: Set (*)).
(Mergeable as as' mrg, Expandable as mrg, Expandable as' mrg) =>
Maybe (OneOrMore as)
-> Maybe (OneOrMore as') -> Maybe (OneOrMore mrg)
`Oom.merge_'` (forall (f :: * -> *) (as :: Set (*)).
OneOrMoreApp ('SetApp f as) -> OneOrMore as
unOneOrMoreApp forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (OneOrMoreApp ('SetApp f as'))
xs')

type Expandable f as as' = Oom.Expandable (f `Map` as) (f `Map` as')
type Collapsable f as as' = Oom.Collapsable (f `Map` as) (f `Map` as')
type Mergeable f as as' mrg = Oom.Mergeable (f `Map` as) (f `Map` as') (f `Map` mrg)