module Pandora.Paradigm.Structure.Ability.Monotonic where

import Pandora.Pattern ((.|..))
import Pandora.Pattern.Functor ((<+>))
import Pandora.Pattern.Functor.Pointable (Pointable)
import Pandora.Pattern.Functor.Avoidable (Avoidable (empty))
import Pandora.Paradigm.Primary.Functor.Function ((!))
import Pandora.Paradigm.Primary.Functor.Predicate (Predicate, satisfy)

class Monotonic a e where
	{-# MINIMAL reduce #-}
	reduce :: (a -> r -> r) -> r -> e -> r

	-- | Version of `reduce` which ignores accumulator
	resolve :: (a -> r) -> r -> e -> r
	resolve a -> r
g = (a -> r -> r) -> r -> e -> r
forall a e r. Monotonic a e => (a -> r -> r) -> r -> e -> r
reduce (a -> r
g (a -> r) -> (((->) a :. (->) r) := a) -> a -> r -> r
forall (v :: * -> * -> *) a c d b.
(Category v, Covariant (v a)) =>
v c d -> ((v a :. v b) := c) -> (v a :. v b) := d
.|.. (!))

instance Monotonic a a where
	reduce :: (a -> r -> r) -> r -> a -> r
reduce a -> r -> r
f r
r a
x = a -> r -> r
f a
x r
r

find :: (Monotonic a e, Pointable t, Avoidable t) => Predicate a -> e -> t a
find :: Predicate a -> e -> t a
find Predicate a
p e
struct = (a -> t a -> t a) -> t a -> e -> t a
forall a e r. Monotonic a e => (a -> r -> r) -> r -> e -> r
reduce (\a
x t a
r -> t a
r t a -> t a -> t a
forall (t :: * -> *) a. Alternative t => t a -> t a -> t a
<+> Predicate a -> a -> t a
forall (t :: * -> *) a.
(Pointable t, Avoidable t) =>
Predicate a -> a -> t a
satisfy Predicate a
p a
x) t a
forall (t :: * -> *) a. Avoidable t => t a
empty e
struct