Parcourir la source

Added Foldable/Traversable instances for SExpr carrier types

Getty Ritter il y a 8 ans
Parent
commit
6196b933f6
2 fichiers modifiés avec 38 ajouts et 9 suppressions
  1. 38 3
      Data/SCargot/Repr.hs
  2. 0 6
      README.md

+ 38 - 3
Data/SCargot/Repr.hs

@@ -14,7 +14,9 @@ module Data.SCargot.Repr
        , fromWellFormed
        ) where
 
---import Data.String (IsString(..))
+import Data.Foldable (Foldable(..))
+import Data.Monoid (Monoid(..), (<>))
+import Data.Traversable (Traversable(..))
 import GHC.Exts (IsList(..), IsString(..))
 
 -- | All S-Expressions can be understood as a sequence
@@ -25,7 +27,7 @@ data SExpr atom
   = SCons (SExpr atom) (SExpr atom)
   | SAtom atom
   | SNil
-    deriving (Eq, Show, Read, Functor)
+    deriving (Eq, Show, Read, Functor, Data)
 
 instance IsString atom => IsString (SExpr atom) where
   fromString = SAtom . fromString
@@ -33,9 +35,22 @@ instance IsString atom => IsString (SExpr atom) where
 instance IsList (SExpr atom) where
   type Item (SExpr atom) = SExpr atom
   fromList = foldr SCons SNil
-  toList   = undefined
+  toList   = go
+    where go (SCons x xs) = x : go xs
+          go SNil         = []
+          go (SAtom {})   = error "Unable to turn atom into list"
+
+instance Foldable SExpr where
+  foldMap _ SNil        = mempty
+  foldMap f (SAtom a)   = f a
+  foldMap f (SCons x y) = foldMap f x <> foldMap f y
 
+instance Traversable SExpr where
+  traverse f SNil        = pure SNil
+  traverse f (SAtom a)   = SAtom <$> f a
+  traverse f (SCons x y) = SCons <$> traverse f x <*> traverse f y
+
+-- | Sometimes the cons-based interface is too low
 --   level, and we'd rather have the lists themselves
 --   exposed. In this case, we have 'RSList' to
 --   represent a well-formed cons list, and 'RSDotted'
@@ -82,6 +97,17 @@ fromRich (RSAtom a) = SAtom a
 fromRich (RSList xs) = foldr SCons SNil (map fromRich xs)
 fromRich (RSDotted xs x) = foldr SCons (SAtom x) (map fromRich xs)
 
+instance Foldable RichSExpr where
+  foldMap f (RSAtom a)      = f a
+  foldMap f (RSList xs)     = mconcat $ map (foldMap f) xs
+  foldMap f (RSDotted xs y) = mconcat (map (foldMap f) xs) <> f y
+
+instance Traversable RichSExpr where
+  traverse f (RSAtom a)      = RSAtom <$> f a
+  traverse f (RSList xs)     = RSList <$> sequenceA (map (traverse f) xs)
+  traverse f (RSDotted xs y) = RSDotted <$> sequenceA (map (traverse f) xs)
+                                        <*> f y
+
 -- | A well-formed s-expression is one which does not
 --   contain any dotted lists. This means that not
 --   every value of @SExpr a@ can be converted to a
@@ -101,6 +127,14 @@ instance IsList (WellFormedSExpr atom) where
 instance IsString atom => IsString (WellFormedSExpr atom) where
   fromString = WFSAtom . fromString
 
+instance Foldable WellFormedSExpr where
+  foldMap f (WFSAtom a)  = f a
+  foldMap f (WFSList xs) = mconcat $ map (foldMap f) xs
+
+instance Traversable WellFormedSExpr where
+  traverse f (WFSAtom a)  = WFSAtom <$> f a
+  traverse f (WFSList xs) = WFSList <$> sequenceA (map (traverse f) xs)
+
 -- | This will be @Nothing@ if the argument contains an
 --   improper list. It should hold that
 --

+ 0 - 6
README.md

@@ -4,12 +4,6 @@ S-expressions often understand subtly different variations on what an
 S-expression is. The goal of S-Cargot is to create several reusable
 components that can be repurposed to nearly any S-expression variant.
 
-Additionally, S-Cargot uses these to include out-of-the-box parsing and
-processing for several existing variations on S-expressions, including
-Common Lisp (**in progresss**), Scheme (**in progress**), the
-[Rivest internet-draft](http://people.csail.mit.edu/rivest/Sexp.txt)
-(**in progress**), and Clojure (**in progress**).
-
 S-Cargot does _not_ aim to be the fastest or most efficient
 s-expression library. If you need speed, then it would probably be
 best to roll your own [AttoParsec]() parser.