s-expression-0.0.0: simple general-purpose s-expressions

Data.Sexp

Synopsis

Documentation

data Sexp f a Source #

a heterogenous list.

a Lisp-2 S-expression, where:

• f is the function namespace
• a is the atom namespace

you could define type Lisp1 a = Sexp a a. with some caveats:

• f is ignored by Monadic methods like joinSexp
• plate doesn't reach the f, even when f ~ a, as the Plated instance is manual, not automatic via Data.

the List case is just a specialized Sexp (), but easier to work with than:

• Sexp (Maybe f) [Sexp f a] (where Nothing would represent List)
• forcing each concrete f to hold a unit case (which would represent List)

examples:

>>> '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"]]]


Constructors

 Atom a List [Sexp f a] Sexp f [Sexp f a]

Instances

 Monad (Sexp f) Source # definitions: return = pureSexp '(>>=)' = bindSexp proofs of laws:left-inverse(1): join . return = idjoin (return m) joinSexp (pureSexp m) joinSexp (Atom m) m left-inverse(2): join . fmap return = id(the Sexp case is elided, the steps being identical to the List case)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) associativity(3): join . join = join . fmap joinTODO  Methods(>>=) :: Sexp f a -> (a -> Sexp f b) -> Sexp f b #(>>) :: Sexp f a -> Sexp f b -> Sexp f b #return :: a -> Sexp f a #fail :: String -> Sexp f a # Functor (Sexp f) Source # Methodsfmap :: (a -> b) -> Sexp f a -> Sexp f b #(<$) :: a -> Sexp f b -> Sexp f a # Source # default instance via the Monad subclass. Methodspure :: a -> Sexp f a #(<*>) :: Sexp f (a -> b) -> Sexp f a -> Sexp f b #(*>) :: Sexp f a -> Sexp f b -> Sexp f b #(<*) :: Sexp f a -> Sexp f b -> Sexp f a # Foldable (Sexp f) Source # Methodsfold :: Monoid m => Sexp f m -> m #foldMap :: Monoid m => (a -> m) -> Sexp f a -> m #foldr :: (a -> b -> b) -> b -> Sexp f a -> b #foldr' :: (a -> b -> b) -> b -> Sexp f a -> b #foldl :: (b -> a -> b) -> b -> Sexp f a -> b #foldl' :: (b -> a -> b) -> b -> Sexp f a -> b #foldr1 :: (a -> a -> a) -> Sexp f a -> a #foldl1 :: (a -> a -> a) -> Sexp f a -> a #toList :: Sexp f a -> [a] #null :: Sexp f a -> Bool #length :: Sexp f a -> Int #elem :: Eq a => a -> Sexp f a -> Bool #maximum :: Ord a => Sexp f a -> a #minimum :: Ord a => Sexp f a -> a #sum :: Num a => Sexp f a -> a #product :: Num a => Sexp f a -> a # Source # Methodstraverse :: Applicative f => (a -> f b) -> Sexp f a -> f (Sexp f b) #sequenceA :: Applicative f => Sexp f (f a) -> f (Sexp f a) #mapM :: Monad m => (a -> m b) -> Sexp f a -> m (Sexp f b) #sequence :: Monad m => Sexp f (m a) -> m (Sexp f a) # IsList (Sexp a b) Source # Associated Typestype Item (Sexp a b) :: * # MethodsfromList :: [Item (Sexp a b)] -> Sexp a b #fromListN :: Int -> [Item (Sexp a b)] -> Sexp a b #toList :: Sexp a b -> [Item (Sexp a b)] # (Eq f, Eq a) => Eq (Sexp f a) Source # Methods(==) :: Sexp f a -> Sexp f a -> Bool #(/=) :: Sexp f a -> Sexp f a -> Bool # (Data a, Data f) => Data (Sexp f a) Source # Methodsgfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Sexp f a -> c (Sexp f a) #gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Sexp f a) #toConstr :: Sexp f a -> Constr #dataTypeOf :: Sexp f a -> DataType #dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c (Sexp f a)) #dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Sexp f a)) #gmapT :: (forall b. Data b => b -> b) -> Sexp f a -> Sexp f a #gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Sexp f a -> r #gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Sexp f a -> r #gmapQ :: (forall d. Data d => d -> u) -> Sexp f a -> [u] #gmapQi :: Int -> (forall d. Data d => d -> u) -> Sexp f a -> u #gmapM :: Monad m => (forall d. Data d => d -> m d) -> Sexp f a -> m (Sexp f a) #gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Sexp f a -> m (Sexp f a) #gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Sexp f a -> m (Sexp f a) # (Ord f, Ord a) => Ord (Sexp f a) Source # Methodscompare :: Sexp f a -> Sexp f a -> Ordering #(<) :: Sexp f a -> Sexp f a -> Bool #(<=) :: Sexp f a -> Sexp f a -> Bool #(>) :: Sexp f a -> Sexp f a -> Bool #(>=) :: Sexp f a -> Sexp f a -> Bool #max :: Sexp f a -> Sexp f a -> Sexp f a #min :: Sexp f a -> Sexp f a -> Sexp f a # (Read f, Read a) => Read (Sexp f a) Source # MethodsreadsPrec :: Int -> ReadS (Sexp f a) #readList :: ReadS [Sexp f a] #readPrec :: ReadPrec (Sexp f a) #readListPrec :: ReadPrec [Sexp f a] # (Show f, Show a) => Show (Sexp f a) Source # MethodsshowsPrec :: Int -> Sexp f a -> ShowS #show :: Sexp f a -> String #showList :: [Sexp f a] -> ShowS # IsString a => IsString (Sexp f a) Source # >>> :set -XOverloadedStrings >>> "x" :: Sexp f String Atom "x"  MethodsfromString :: String -> Sexp f a # Generic (Sexp f a) Source # Associated Typestype Rep (Sexp f a) :: * -> * # Methodsfrom :: Sexp f a -> Rep (Sexp f a) x #to :: Rep (Sexp f a) x -> Sexp f a # Semigroup (Sexp a b) Source # Methods(<>) :: Sexp a b -> Sexp a b -> Sexp a b #sconcat :: NonEmpty (Sexp a b) -> Sexp a b #stimes :: Integral b => b -> Sexp a b -> Sexp a b # Monoid (Sexp a b) Source # Methodsmempty :: Sexp a b #mappend :: Sexp a b -> Sexp a b -> Sexp a b #mconcat :: [Sexp a b] -> Sexp a b # Plated (Sexp f a) Source # Methodsplate :: Traversal' (Sexp f a) (Sexp f a) # type Rep (Sexp f a) Source # type Rep (Sexp f a) = D1 (MetaData "Sexp" "Data.Sexp" "s-expression-0.0.0-G3iGEh3gocX9fdzOVwuTpc" False) ((:+:) (C1 (MetaCons "Atom" PrefixI False) (S1 (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 a))) ((:+:) (C1 (MetaCons "List" PrefixI False) (S1 (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 [Sexp f a]))) (C1 (MetaCons "Sexp" PrefixI False) ((:*:) (S1 (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 f)) (S1 (MetaSel (Nothing Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 [Sexp f a])))))) type Item (Sexp a b) Source # type Item (Sexp a b) = Sexp a b type Sexp_ = Sexp Void Source # 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). toSexp :: (r -> Either a [r]) -> r -> Sexp_ a Source # data ByteSexp = Atom ByteString | List [ByteSexp] bytesexp2sexp :: ByteSexp -> Sexp_ ByteString bytesexp2sexp = toSexp$ case
Atom s  -> Left  s
List es -> Right es


pureSexp :: a -> Sexp f a Source #

pureSexp = Atom

bindSexp :: Sexp f a -> (a -> Sexp f b) -> Sexp f b Source #

joinSexp :: Sexp f (Sexp f a) -> Sexp f a Source #

toSexpList :: Sexp f a -> [Sexp f a] Source #

refines any Sexp to a list, which can be given to the List.

appendSexp :: Sexp f a -> Sexp f a -> Sexp f a Source #

>>> appendSexp (Atom "f") (List [Atom "x"])
List [Atom "f",Atom "x"]


emptySexp :: Sexp f a Source #

emptySexp = List []

evalSexp :: Monad m => ([a] -> m a) -> ([a] -> g -> m a) -> Sexp g a -> m a Source #

fold over an sexp.

i.e. strictly evaluate a sexp ("all the way") to an atom, within any monadic context.

evalSplatSexp :: (Monad m, Monoid b) => (b -> g -> m b) -> Sexp g b -> m b Source #

>>> 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
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)

splatSexpList :: (Applicative m, Monoid b) => (Sexp g b -> m b) -> [Sexp g b] -> m b Source #

when a Sexp's atoms are Monoidal ("list-like"), after evaluating some expressions into atoms, we can "splat" them back together.

splatList takes:

• an evaluator eval
• and a list of s-expressions es to evaluate in sequence.

listSexp :: [a] -> Sexp f a Source #

inject a list of atoms.

>>> listSexp [1,2,3]
List [Atom 1,Atom 2,Atom 3]