packages feed

pandora-0.4.9: Pandora/Paradigm/Primary/Functor/Conclusion.hs

module Pandora.Paradigm.Primary.Functor.Conclusion where

import Pandora.Core.Functor (type (~>))
import Pandora.Pattern.Semigroupoid ((.))
import Pandora.Pattern.Morphism.Straight (Straight (Straight))
import Pandora.Pattern.Category (identity, (#))
import Pandora.Pattern.Functor.Covariant (Covariant ((<-|-)))
import Pandora.Pattern.Functor.Semimonoidal (Semimonoidal (mult))
import Pandora.Pattern.Functor.Monoidal (Monoidal (unit))
import Pandora.Pattern.Functor.Traversable (Traversable ((<<-)))
import Pandora.Pattern.Functor.Bindable (Bindable ((=<<)))
import Pandora.Pattern.Functor.Monad (Monad)
import Pandora.Pattern.Functor.Bivariant (Bivariant ((<->)))
import Pandora.Pattern.Object.Setoid (Setoid ((==)))
import Pandora.Pattern.Object.Chain (Chain ((<=>)))
import Pandora.Pattern.Object.Semigroup (Semigroup ((+)))
import Pandora.Paradigm.Primary.Object.Boolean (Boolean (False))
import Pandora.Paradigm.Primary.Object.Ordering (Ordering (Less, Greater))
import Pandora.Paradigm.Primary.Algebraic.Product ((:*:) ((:*:)))
import Pandora.Paradigm.Primary.Algebraic.Sum ((:+:) (Option, Adoption))
import Pandora.Pattern.Morphism.Flip (Flip (Flip))
import Pandora.Paradigm.Controlflow.Effect.Interpreted (Schematic, Interpreted (Primary, run, unite, (!)))
import Pandora.Paradigm.Controlflow.Effect.Transformer.Monadic (Monadic (wrap), (:>) (TM))
import Pandora.Paradigm.Controlflow.Effect.Adaptable (Adaptable (adapt))
import Pandora.Paradigm.Schemes.UT (UT (UT), type (<.:>))
import Pandora.Paradigm.Primary.Algebraic.Exponential (type (-->))
import Pandora.Paradigm.Primary.Algebraic.One (One (One))
import Pandora.Paradigm.Primary.Algebraic (point)

data Conclusion e a = Failure e | Success a

instance Covariant (->) (->) (Conclusion e) where
	f <-|- Success x = Success ! f x
	_ <-|- Failure y = Failure y

instance Covariant (->) (->) (Flip Conclusion e) where
	_ <-|- Flip (Success x) = Flip ! Success x
	f <-|- Flip (Failure y) = Flip . Failure ! f y

instance Semimonoidal (-->) (:*:) (:*:) (Conclusion e) where
	mult = Straight ! \case
		Success x :*: Success y -> Success ! x :*: y
		Failure x :*: _ -> Failure x
		_ :*: Failure x -> Failure x

instance Monoidal (-->) (-->) (:*:) (:*:) (Conclusion e) where
	unit _ = Straight ! Success . (! One) . run

instance Semigroup e => Semimonoidal (-->) (:*:) (:+:) (Conclusion e) where
	mult = Straight ! \case
		Failure _ :*: x -> Adoption <-|- x
		Success x :*: _ -> Option <-|- Success x

instance Traversable (->) (->) (Conclusion e) where
	(<<-) :: (Covariant (->) (->) u, Monoidal (-->) (-->) (:*:) (:*:) u, Semimonoidal (-->) (:*:) (:*:) u)
		 => (a -> u b) -> Conclusion e a -> u (Conclusion e b)
	_ <<- Failure y = point ! Failure y
	f <<- Success x = Success <-|- f x

instance Bindable (->) (Conclusion e) where
	f =<< Success x = f x
	_ =<< Failure y = Failure y

--instance Monad (Conclusion e) where

instance Bivariant (->) (->) (->) Conclusion where
	f <-> g = conclusion # Failure . f # Success . g

instance (Setoid e, Setoid a) => Setoid (Conclusion e a) where
	Success x == Success y = x == y
	Failure x == Failure y = x == y
	_ == _ = False

instance (Chain e, Chain a) => Chain (Conclusion e a) where
	Success x <=> Success y = x <=> y
	Failure x <=> Failure y = x <=> y
	Failure _ <=> Success _ = Less
	Success _ <=> Failure _ = Greater

instance (Semigroup e, Semigroup a) => Semigroup (Conclusion e a) where
	Success x + Success y = Success ! x + y
	Failure x + Failure y = Failure ! x + y
	Failure _ + Success y = Success y
	Success x + Failure _ = Success x

conclusion :: (e -> r) -> (a -> r) -> Conclusion e a -> r
conclusion f _ (Failure x) = f x
conclusion _ s (Success x) = s x

fail :: (e -> r) -> Conclusion e ~> Conclusion r
fail f (Failure x) = Failure ! f x
fail _ (Success y) = Success y

instance Interpreted (->) (Conclusion e) where
	type Primary (Conclusion e) a = Conclusion e a
	run = identity
	unite = identity

type instance Schematic Monad (Conclusion e) = (<.:>) (Conclusion e)

instance Monadic (->) (Conclusion e) where
	wrap = TM . UT . point

type Failable e t = Adaptable t (->) (Conclusion e)

failure :: Failable e t => e -> t a
failure = adapt . Failure

class Catchable e t where
	catch :: t a -> (e -> t a) -> t a

instance Catchable e (Conclusion e) where
	catch (Failure e) handle = handle e
	catch (Success x) _ = Success x

instance (Monoidal (-->) (-->) (:*:) (:*:) u, Bindable (->) u) => Catchable e (Conclusion e <.:> u) where
	catch (UT x) handle = let conclude = conclusion # run . handle # point . Success
		in UT ! conclude =<< x