module Pandora.Pattern.Functor.Applicative where

import Pandora.Core.Functor (type (:.), type (:=))
import Pandora.Pattern.Functor.Covariant (Covariant ((<$>), (<$)))

infixl 4 <*>, <*, *>
infixl 3 <**>
infixl 2 <***>
infixl 1 <****>

{- |
> When providing a new instance, you should ensure it satisfies:
> * Interpreted: (.) <$> u <*> v <*> w ≡ u <*> (v <*> w)
> * Left interchange: x <*> (f <$> y) ≡ (. f) <$> x <*> y
> * Right interchange: f <$> (x <*> y) ≡ (f .) <$> x <*> y
-}

class Covariant t => Applicative t where
	{-# MINIMAL (<*>) #-}
	-- | Infix version of 'apply'
	(<*>) :: t (a -> b) -> t a -> t b
	-- | Prefix version of '<*>'
	apply :: t (a -> b) -> t a -> t b
	apply t (a -> b)
f t a
x = t (a -> b)
f t (a -> b) -> t a -> t b
forall (t :: * -> *) a b. Applicative t => t (a -> b) -> t a -> t b
<*> t a
x
	-- | Sequence actions, discarding the value of the first argument
	(*>) :: t a -> t b -> t b
	t a
x *> t b
y = ((\b
z -> b
z) (b -> b) -> t a -> t (b -> b)
forall (t :: * -> *) a b. Covariant t => a -> t b -> t a
<$ t a
x) t (b -> b) -> t b -> t b
forall (t :: * -> *) a b. Applicative t => t (a -> b) -> t a -> t b
<*> t b
y
	-- | Sequence actions, discarding the value of the second argument
	(<*) :: t a -> t b -> t a
	t a
x <* t b
y = t b
y t b -> t a -> t a
forall (t :: * -> *) a b. Applicative t => t a -> t b -> t b
*> t a
x
	-- | Repeat an action indefinitely
	forever :: t a -> t b
	forever t a
x = t a
x t a -> t b -> t b
forall (t :: * -> *) a b. Applicative t => t a -> t b -> t b
*> t a -> t b
forall (t :: * -> *) a b. Applicative t => t a -> t b
forever t a
x
	-- | Flipped version of '<*>'
	(<%>) :: t a -> t (a -> b) -> t b
	t a
x <%> t (a -> b)
f = (\a
x' a -> b
f' -> a -> b
f' a
x') (a -> (a -> b) -> b) -> t a -> t ((a -> b) -> b)
forall (t :: * -> *) a b. Covariant t => (a -> b) -> t a -> t b
<$> t a
x t ((a -> b) -> b) -> t (a -> b) -> t b
forall (t :: * -> *) a b. Applicative t => t (a -> b) -> t a -> t b
<*> t (a -> b)
f
	-- | Infix versions of `apply` with various nesting levels
	(<**>) :: Applicative u => t :. u := (a -> b) -> t :. u := a -> t :. u := b
	(t :. u) := (a -> b)
f <**> (t :. u) := a
x = u (a -> b) -> u a -> u b
forall (t :: * -> *) a b. Applicative t => t (a -> b) -> t a -> t b
(<*>) (u (a -> b) -> u a -> u b)
-> ((t :. u) := (a -> b)) -> t (u a -> u b)
forall (t :: * -> *) a b. Covariant t => (a -> b) -> t a -> t b
<$> (t :. u) := (a -> b)
f t (u a -> u b) -> ((t :. u) := a) -> (t :. u) := b
forall (t :: * -> *) a b. Applicative t => t (a -> b) -> t a -> t b
<*> (t :. u) := a
x
	(<***>) :: (Applicative u, Applicative v) => t :. u :. v := (a -> b)
		-> t :. u :. v := a -> t :. u :. v := b
	(t :. (u :. v)) := (a -> b)
f <***> (t :. (u :. v)) := a
x = ((u :. v) := (a -> b)) -> ((u :. v) := a) -> (u :. v) := b
forall (t :: * -> *) (u :: * -> *) a b.
(Applicative t, Applicative u) =>
((t :. u) := (a -> b)) -> ((t :. u) := a) -> (t :. u) := b
(<**>) (((u :. v) := (a -> b)) -> ((u :. v) := a) -> (u :. v) := b)
-> ((t :. (u :. v)) := (a -> b))
-> t (((u :. v) := a) -> (u :. v) := b)
forall (t :: * -> *) a b. Covariant t => (a -> b) -> t a -> t b
<$> (t :. (u :. v)) := (a -> b)
f t (((u :. v) := a) -> (u :. v) := b)
-> ((t :. (u :. v)) := a) -> (t :. (u :. v)) := b
forall (t :: * -> *) a b. Applicative t => t (a -> b) -> t a -> t b
<*> (t :. (u :. v)) := a
x
	(<****>) :: (Applicative u, Applicative v, Applicative w)
		=> t :. u :. v :. w := (a -> b)
		-> t :. u :. v :. w := a
		-> t :. u :. v :. w := b
	(t :. (u :. (v :. w))) := (a -> b)
f <****> (t :. (u :. (v :. w))) := a
x = ((u :. (v :. w)) := (a -> b))
-> ((u :. (v :. w)) := a) -> (u :. (v :. w)) := b
forall (t :: * -> *) (u :: * -> *) (v :: * -> *) a b.
(Applicative t, Applicative u, Applicative v) =>
((t :. (u :. v)) := (a -> b))
-> ((t :. (u :. v)) := a) -> (t :. (u :. v)) := b
(<***>) (((u :. (v :. w)) := (a -> b))
 -> ((u :. (v :. w)) := a) -> (u :. (v :. w)) := b)
-> ((t :. (u :. (v :. w))) := (a -> b))
-> t (((u :. (v :. w)) := a) -> (u :. (v :. w)) := b)
forall (t :: * -> *) a b. Covariant t => (a -> b) -> t a -> t b
<$> (t :. (u :. (v :. w))) := (a -> b)
f t (((u :. (v :. w)) := a) -> (u :. (v :. w)) := b)
-> ((t :. (u :. (v :. w))) := a) -> (t :. (u :. (v :. w))) := b
forall (t :: * -> *) a b. Applicative t => t (a -> b) -> t a -> t b
<*> (t :. (u :. (v :. w))) := a
x