module Data.PropertyList.Types
(
PropertyList
, PartialPropertyList
, completePropertyList
, completePropertyListBy
, completePropertyListByM
) where
import Data.PropertyList.Algebra
import Control.Applicative (Applicative(..))
import Data.Functor.Foldable (Fix(..))
import qualified Data.Functor.Foldable as RS
import Control.Monad (liftM)
import Control.Monad.Free (Free(..))
import Data.Functor.Identity (Identity(..))
import Data.Foldable (Foldable)
import Data.Traversable (Traversable(traverse), mapM)
import Unsafe.Coerce (unsafeCoerce)
newtype PropertyList = PL { unPL :: Fix PropertyListS }
deriving (Eq, Ord)
instance Show PropertyList where
show pl = showsPrec 0 pl " :: PropertyList"
showsPrec p (PL (Fix x)) = showParen (p > 10) $ case x of
PLArray arr -> showString "plArray " . showsPrec 11 (fmap PL arr)
PLData bs -> showString "plData " . showsPrec 11 bs
PLDate time -> showString "plDate " . showsPrec 11 time
PLDict dict -> showString "plDict " . showsPrec 11 (fmap PL dict)
PLReal dbl -> showString "plReal " . showsPrec 11 dbl
PLInt int -> showString "plInt " . showsPrec 11 int
PLString str -> showString "plString " . showsPrec 11 str
PLBool bool -> showString "plBool " . showsPrec 11 bool
type instance RS.Base PropertyList = PropertyListS
instance RS.Foldable PropertyList where
project = runIdentity . plistCoalgebra
instance RS.Unfoldable PropertyList where
embed = plistAlgebra . Identity
inPL :: PropertyListS PropertyList -> PropertyList
inPL = PL . Fix . fmap unPL
outPL :: PropertyList -> PropertyListS PropertyList
outPL = fmap PL . outF . unPL
where outF (Fix x) = x
instance PListAlgebra Identity PropertyList where
plistAlgebra = inPL . runIdentity
instance PListCoalgebra Identity a => PListAlgebra (Either a) PropertyList where
plistAlgebra = either toPlist (plistAlgebra . Identity)
instance InitialPList Identity PropertyList
instance Applicative f => PListCoalgebra f PropertyList where
plistCoalgebra = pure . outPL
instance TerminalPList Identity PropertyList
newtype PartialPropertyList a = PPL {unPPL :: Free PropertyListS a}
deriving (Eq, Ord, Functor, Applicative, Monad, Foldable, Traversable)
inPPL :: PropertyListS (PartialPropertyList a) -> PartialPropertyList a
inPPL = PPL . Free . fmap unPPL
instance Show a => Show (PartialPropertyList a) where
showsPrec p (PPL x) = showParen (p > 10) $ case x of
Pure a -> showString "return " . showsPrec 11 a
Free x -> case x of
PLArray arr -> showString "plArray " . showsPrec 11 (fmap PPL arr)
PLData bs -> showString "plData " . showsPrec 11 bs
PLDate time -> showString "plDate " . showsPrec 11 time
PLDict dict -> showString "plDict " . showsPrec 11 (fmap PPL dict)
PLReal dbl -> showString "plReal " . showsPrec 11 dbl
PLInt int -> showString "plInt " . showsPrec 11 int
PLString str -> showString "plString " . showsPrec 11 str
PLBool bool -> showString "plBool " . showsPrec 11 bool
instance PListAlgebra Identity (PartialPropertyList a) where
plistAlgebra = inPPL . runIdentity
instance PListAlgebra Maybe (PartialPropertyList ()) where
plistAlgebra = maybe (pure ()) inPPL
instance PListAlgebra (Either a) (PartialPropertyList a) where
plistAlgebra = either pure inPPL
instance InitialPList (Either a) (PartialPropertyList a) where
instance PListCoalgebra (Either a) (PartialPropertyList a) where
plistCoalgebra (PPL (Pure a)) = Left a
plistCoalgebra (PPL (Free a)) = Right (fmap PPL a)
instance TerminalPList (Either a) (PartialPropertyList a) where
instance PListCoalgebra Maybe (PartialPropertyList a) where
plistCoalgebra (PPL (Pure _)) = Nothing
plistCoalgebra (PPL (Free x)) = Just (fmap PPL x)
completePropertyList :: PListCoalgebra Identity a => PartialPropertyList a -> PropertyList
completePropertyList = foldPList
(plistAlgebra :: PListCoalgebra Identity a => Either a (PropertyListS PropertyList) -> PropertyList)
completePropertyListBy :: (Applicative f, PListCoalgebra Identity b)
=> (a -> f b) -> PartialPropertyList a -> f PropertyList
completePropertyListBy f = fmap completePropertyList . traverse f
completePropertyListByM :: (Monad m, PListCoalgebra Identity b)
=> (a -> m b) -> PartialPropertyList a -> m PropertyList
completePropertyListByM f = liftM completePropertyList . Data.Traversable.mapM f