gdritter repos s-cargot / 6196b93
Added Foldable/Traversable instances for SExpr carrier types Getty Ritter 8 years ago
2 changed file(s) with 38 addition(s) and 10 deletion(s). Collapse all Expand all
1414 , fromWellFormed
1515 ) where
1616
17 --import Data.String (IsString(..))
17 import Data.Foldable (Foldable(..))
18 import Data.Monoid (Monoid(..), (<>))
19 import Data.Traversable (Traversable(..))
1820 import GHC.Exts (IsList(..), IsString(..))
1921
2022 -- | All S-Expressions can be understood as a sequence
2527 = SCons (SExpr atom) (SExpr atom)
2628 | SAtom atom
2729 | SNil
28 deriving (Eq, Show, Read, Functor)
30 deriving (Eq, Show, Read, Functor, Data)
2931
3032 instance IsString atom => IsString (SExpr atom) where
3133 fromString = SAtom . fromString
3335 instance IsList (SExpr atom) where
3436 type Item (SExpr atom) = SExpr atom
3537 fromList = foldr SCons SNil
36 toList = undefined
38 toList = go
39 where go (SCons x xs) = x : go xs
40 go SNil = []
41 go (SAtom {}) = error "Unable to turn atom into list"
3742
38 -- | sometimes, the cons-based interface is too low
43 instance Foldable SExpr where
44 foldMap _ SNil = mempty
45 foldMap f (SAtom a) = f a
46 foldMap f (SCons x y) = foldMap f x <> foldMap f y
47
48 instance Traversable SExpr where
49 traverse f SNil = pure SNil
50 traverse f (SAtom a) = SAtom <$> f a
51 traverse f (SCons x y) = SCons <$> traverse f x <*> traverse f y
52
53 -- | Sometimes the cons-based interface is too low
3954 -- level, and we'd rather have the lists themselves
4055 -- exposed. In this case, we have 'RSList' to
4156 -- represent a well-formed cons list, and 'RSDotted'
8297 fromRich (RSList xs) = foldr SCons SNil (map fromRich xs)
8398 fromRich (RSDotted xs x) = foldr SCons (SAtom x) (map fromRich xs)
8499
100 instance Foldable RichSExpr where
101 foldMap f (RSAtom a) = f a
102 foldMap f (RSList xs) = mconcat $ map (foldMap f) xs
103 foldMap f (RSDotted xs y) = mconcat (map (foldMap f) xs) <> f y
104
105 instance Traversable RichSExpr where
106 traverse f (RSAtom a) = RSAtom <$> f a
107 traverse f (RSList xs) = RSList <$> sequenceA (map (traverse f) xs)
108 traverse f (RSDotted xs y) = RSDotted <$> sequenceA (map (traverse f) xs)
109 <*> f y
110
85111 -- | A well-formed s-expression is one which does not
86112 -- contain any dotted lists. This means that not
87113 -- every value of @SExpr a@ can be converted to a
100126
101127 instance IsString atom => IsString (WellFormedSExpr atom) where
102128 fromString = WFSAtom . fromString
129
130 instance Foldable WellFormedSExpr where
131 foldMap f (WFSAtom a) = f a
132 foldMap f (WFSList xs) = mconcat $ map (foldMap f) xs
133
134 instance Traversable WellFormedSExpr where
135 traverse f (WFSAtom a) = WFSAtom <$> f a
136 traverse f (WFSList xs) = WFSList <$> sequenceA (map (traverse f) xs)
103137
104138 -- | This will be @Nothing@ if the argument contains an
105139 -- improper list. It should hold that
33 S-expressions often understand subtly different variations on what an
44 S-expression is. The goal of S-Cargot is to create several reusable
55 components that can be repurposed to nearly any S-expression variant.
6
7 Additionally, S-Cargot uses these to include out-of-the-box parsing and
8 processing for several existing variations on S-expressions, including
9 Common Lisp (**in progresss**), Scheme (**in progress**), the
10 [Rivest internet-draft](http://people.csail.mit.edu/rivest/Sexp.txt)
11 (**in progress**), and Clojure (**in progress**).
126
137 S-Cargot does _not_ aim to be the fastest or most efficient
148 s-expression library. If you need speed, then it would probably be