-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | simple general-purpose s-expressions -- -- this package provides general-purpose functionality for manipulating -- s-expressions. like: -- --
-- data Sexp f a -- = Atom a -- | List [Sexp f a] -- | Sexp f [Sexp f a] ---- -- which lets you provide your own custom function name that interprets -- its arguments. -- -- e.g. TODO -- -- for efficient parsing/printing, use: -- -- @package s-expression @version 0.0.0 module Data.Sexp -- | a heterogenous list. -- -- a Lisp-2 S-expression, where: -- --
-- >>> 'toList' (List [Atom "f",Atom "x",List [Atom "g",Atom "y"],Atom "z"]) -- ["f","x","g","y","z"] ---- --
-- >>> :{
-- let doubleSexp e = do
-- x <- e
-- listSexp [x,x]
-- :}
--
-- >>> doubleSexp (List [Atom "f", Sexp () [Atom "a", Atom "b"]])
-- List [List [Atom "f",Atom "f"],Sexp () [List [Atom "a",Atom "a"],List [Atom "b",Atom "b"]]]
--
data Sexp f a
Atom :: a -> Sexp f a
List :: [Sexp f a] -> Sexp f a
Sexp :: f -> [Sexp f a] -> Sexp f a
-- | isomorphic to:
--
-- -- data Sexp_ a -- = Atom_ a -- | List_ [Sexp_ a] ---- -- when you only care about lists (e.g. to interface with other -- s-expression libraries). type Sexp_ = Sexp Void -- |
-- data ByteSexp -- = Atom ByteString -- | List [ByteSexp] -- -- bytesexp2sexp :: ByteSexp -> Sexp_ ByteString -- bytesexp2sexp = toSexp $ case -- Atom s -> Left s -- List es -> Right es --toSexp :: (r -> Either a [r]) -> (r -> Sexp_ a) -- | default instance via the Monad subclass. -- | definitions: -- --
-- return = pureSexp -- '(>>=)' = bindSexp ---- -- proofs of laws: -- --
join (return m) -- joinSexp (pureSexp m) joinSexp (Atom m) m
join (fmap -- return m) joinSexp (fmap pureSexp m) joinSexp (fmap Atom m) -- case -- analysis case m of Atom x -> joinSexp (Atom (Atom x)) -- by -- definition of joinSexp Atom x List ms -> joinSexp (List (fmap (fmap -- Atom) ms) -- by definition of joinSexp List (fmap joinSexp (fmap (fmap -- Atom) ms)) -- functor composition List (fmap (joinSexp . fmap Atom) -- ms) List (fmap (join . fmap return) ms) -- by induction List (fmap id -- ms) -- functor identity List ms -- both cases are identity m --where:
fmap f = case Atom x -> f x List ms -> List -- (fmap (fmap f) ms) join = case Atom x -> x List ms -> List (fmap -- joinSexp ms)
TODO --
-- >>> :set -XOverloadedStrings -- -- >>> "x" :: Sexp f String -- Atom "x" ---- |
-- pureSexp = Atom --pureSexp :: a -> Sexp f a bindSexp :: Sexp f a -> (a -> Sexp f b) -> Sexp f b joinSexp :: Sexp f (Sexp f a) -> Sexp f a -- | refines any Sexp to a list, which can be given to the List. toSexpList :: Sexp f a -> [Sexp f a] -- |
-- >>> appendSexp (Atom "f") (List [Atom "x"]) -- List [Atom "f",Atom "x"] --appendSexp :: Sexp f a -> Sexp f a -> Sexp f a -- |
-- emptySexp = List [] --emptySexp :: Sexp f a -- | fold over an sexp. -- -- i.e. strictly evaluate a sexp ("all the way") to an atom, within any -- monadic context. evalSexp :: (Monad m) => ([a] -> m a) -> ([a] -> g -> m a) -> Sexp g a -> m a -- |
-- >>> data ArithFunc = Add | Multiply | Negate deriving Show
--
-- >>> let badArith = Sexp Negate [Atom 1, Atom 2, Atom 3] :: Sexp ArithFunc Integer
--
-- >>> let goodArith = Sexp Add [Sexp Multiply [], Sexp Negate [Atom (10::Integer)], Sexp Multiply [Atom 2, Atom 3, Atom 4]]
--
-- >>> :set -XLambdaCase
--
-- >>> :{
-- let evalArith = \case
-- Add -> \case
-- xs -> Just [sum xs]
-- Multiply -> \case
-- xs -> Just [product xs]
-- Negate -> \case
-- [x] -> Just [negate x]
-- _ -> Nothing
-- :}
--
-- >>> evalSplatSexp (flip evalArith) (fmap (:[]) badArith) -- wrong arity
-- Nothing
--
-- >>> evalSplatSexp (flip evalArith) (fmap (:[]) goodArith) -- (+ (*) (- 10) (* 2 3 4))
-- Just [15]
--
--
-- specializing, as above, (m ~ Maybe), (b ~
-- [Integer]), (g ~ ArithFunc):
--
-- -- evalSplatSexp :: ([Integer] -> ArithFunc -> Maybe [Integer]) -> (Sexp ArithFunc [Integer] -> Maybe [Integer]) ---- --
-- evalSplatSexp apply = evalSexp ('pure'.'fold') (apply.fold)
--
evalSplatSexp :: (Monad m, Monoid b) => (b -> g -> m b) -> (Sexp g b -> m b)
-- | when a Sexp's atoms are Monoidal ("list-like"), after
-- evaluating some expressions into atoms, we can "splat" them back
-- together.
--
-- splatList takes:
--
-- -- >>> listSexp [1,2,3] -- List [Atom 1,Atom 2,Atom 3] --listSexp :: [a] -> Sexp f a instance Data.Semigroup.Semigroup (Data.Sexp.Sexp a b) instance GHC.Base.Monoid (Data.Sexp.Sexp a b) instance GHC.Exts.IsList (Data.Sexp.Sexp a b) instance GHC.Generics.Generic (Data.Sexp.Sexp f a) instance (Data.Data.Data a, Data.Data.Data f) => Data.Data.Data (Data.Sexp.Sexp f a) instance Data.Traversable.Traversable (Data.Sexp.Sexp f) instance Data.Foldable.Foldable (Data.Sexp.Sexp f) instance GHC.Base.Functor (Data.Sexp.Sexp f) instance (GHC.Classes.Ord f, GHC.Classes.Ord a) => GHC.Classes.Ord (Data.Sexp.Sexp f a) instance (GHC.Classes.Eq f, GHC.Classes.Eq a) => GHC.Classes.Eq (Data.Sexp.Sexp f a) instance (GHC.Read.Read f, GHC.Read.Read a) => GHC.Read.Read (Data.Sexp.Sexp f a) instance (GHC.Show.Show f, GHC.Show.Show a) => GHC.Show.Show (Data.Sexp.Sexp f a) instance GHC.Base.Applicative (Data.Sexp.Sexp f) instance GHC.Base.Monad (Data.Sexp.Sexp f) instance Control.Lens.Plated.Plated (Data.Sexp.Sexp f a) instance Data.String.IsString a => Data.String.IsString (Data.Sexp.Sexp f a) -- | (see source) module Data.Sexp.Example exampleSexp :: Sexp () String module Data.Sexp.Main main :: IO () mainWith :: t -> IO ()