{-# LANGUAGE AllowAmbiguousTypes #-}
module Pandora.Paradigm.Structure.Interface.Stack where

import Pandora.Paradigm.Primary.Functor.Maybe (Maybe)
import Pandora.Paradigm.Inventory.Some.State (State)
import Pandora.Paradigm.Inventory.Some.Optics (Lens)

{- |
> When providing a new instance, you should ensure it satisfies:
> * Idempotency: item @Push x . morph @Pop ≡ identity
-}

class Stack t where
	type Topping t :: * -> *
	type Popping t :: * -> *
	type Pushing t :: * -> *
	top :: Lens (Topping t) (t e) e
	-- TODO: In case of nonempty list we know that we return an element
	pop :: State ((Popping t) e) (Maybe e)
	push :: e -> State ((Pushing t) e) e