{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Semigroup.Semilattice
( FreeSemilattice
, fromNonEmpty
, toNonEmpty
) where
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NE
import Data.IntSet (IntSet)
import Data.Semigroup ( All
, Any
#if __GLASGOW_HASKELL__ < 808
, Semigroup
#endif
, sconcat)
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Void (Void)
import Data.Algebra.Free ( AlgebraType
, AlgebraType0
, FreeAlgebra (..)
)
import Data.Semigroup.Abelian (AbelianSemigroup)
class AbelianSemigroup m => Semilattice m
instance Semilattice Void
instance Semilattice ()
instance Semilattice All
instance Semilattice Any
instance Ord a => Semilattice (Set a)
instance Semilattice IntSet
newtype FreeSemilattice a = FreeSemilattice (Set a)
deriving (Ord, Eq, Show, Semigroup)
instance Ord a => AbelianSemigroup (FreeSemilattice a)
instance Ord a => Semilattice (FreeSemilattice a)
fromNonEmpty :: Ord a => NonEmpty a -> FreeSemilattice a
fromNonEmpty = FreeSemilattice . Set.fromList . NE.toList
toNonEmpty :: FreeSemilattice a -> NonEmpty a
toNonEmpty (FreeSemilattice as) = NE.fromList $ Set.toList as
type instance AlgebraType0 FreeSemilattice a = Ord a
type instance AlgebraType FreeSemilattice a = (Ord a, Semilattice a)
instance FreeAlgebra FreeSemilattice where
returnFree a = FreeSemilattice $ Set.singleton a
foldMapFree f (FreeSemilattice as) = sconcat $ fmap f $ NE.fromList $ Set.toList as