Safe Haskell | None |
---|---|
Language | Haskell2010 |
- data Sexp f a
- type Sexp_ = Sexp Void
- toSexp :: (r -> Either a [r]) -> r -> Sexp_ a
- 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
- toSexpList :: Sexp f a -> [Sexp f a]
- appendSexp :: Sexp f a -> Sexp f a -> Sexp f a
- emptySexp :: Sexp f a
- evalSexp :: Monad m => ([a] -> m a) -> ([a] -> g -> m a) -> Sexp g a -> m a
- evalSplatSexp :: (Monad m, Monoid b) => (b -> g -> m b) -> Sexp g b -> m b
- splatSexpList :: (Applicative m, Monoid b) => (Sexp g b -> m b) -> [Sexp g b] -> m b
- listSexp :: [a] -> Sexp f a
Documentation
a heterogenous list.
a Lisp-2 S-expression, where:
f
is the function namespacea
is the atom namespace
you could define type Lisp1 a = Sexp a a
. with some caveats:
f
is ignored byMonad
ic methods likejoinSexp
plate
doesn't reach thef
, even whenf ~ a
, as thePlated
instance is manual, not automatic viaData
.
the List
case is just a specialized
, but easier to work with than:Sexp
()
Sexp (Maybe f) [Sexp f a]
(where Nothing would representList
)- forcing each concrete
f
to hold a unit case (which would representList
)
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"]]]
Monad (Sexp f) Source # | definitions:
proofs of laws:
|
Functor (Sexp f) Source # | |
Applicative (Sexp f) Source # | default instance via the |
Foldable (Sexp f) Source # | |
Traversable (Sexp f) Source # | |
IsList (Sexp a b) Source # | |
(Eq f, Eq a) => Eq (Sexp f a) Source # | |
(Data a, Data f) => Data (Sexp f a) Source # | |
(Ord f, Ord a) => Ord (Sexp f a) Source # | |
(Read f, Read a) => Read (Sexp f a) Source # | |
(Show f, Show a) => Show (Sexp f a) Source # | |
IsString a => IsString (Sexp f a) Source # |
|
Generic (Sexp f a) Source # | |
Semigroup (Sexp a b) Source # | |
Monoid (Sexp a b) Source # | |
Plated (Sexp f a) Source # | |
type Rep (Sexp f a) Source # | |
type Item (Sexp a b) Source # | |
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).
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"]
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 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
)
splatSexpList :: (Applicative m, Monoid b) => (Sexp g b -> m b) -> [Sexp g b] -> m b Source #
when a Sexp's atoms are Monoid
al ("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.