module Data.Apart.Structures.Stack (Stack, insert, singleton, foldaway, final) where import "contravariant" Data.Functor.Contravariant (Predicate (..)) import "free" Control.Comonad.Cofree (Cofree (..), unwrap) import Data.Apart.Transformations (Segmented (..)) -- | Or non-empty list. type Stack = Cofree Maybe singleton :: a -> Stack a singleton x = x :< Nothing insert :: a -> Stack a -> Stack a insert x = (:<) x . Just -- when I understand how to use partially applied -- type families correctly, it can be rewritten -- slightly as natural transformation foldaway :: Foldable t => t a -> Segmented Stack a foldaway = foldr (\el -> Just . (:<) el) Nothing final :: Eq a => Predicate (Stack a) final = Predicate $ \s -> unwrap s == Nothing