|
@@ -14,7 +14,9 @@ module Data.SCargot.Repr
|
|
, fromWellFormed
|
|
, fromWellFormed
|
|
) where
|
|
) where
|
|
|
|
|
|
---import Data.String (IsString(..))
|
|
|
|
|
|
+import Data.Foldable (Foldable(..))
|
|
|
|
+import Data.Monoid (Monoid(..), (<>))
|
|
|
|
+import Data.Traversable (Traversable(..))
|
|
import GHC.Exts (IsList(..), IsString(..))
|
|
import GHC.Exts (IsList(..), IsString(..))
|
|
|
|
|
|
-- | All S-Expressions can be understood as a sequence
|
|
-- | All S-Expressions can be understood as a sequence
|
|
@@ -25,7 +27,7 @@ data SExpr atom
|
|
= SCons (SExpr atom) (SExpr atom)
|
|
= SCons (SExpr atom) (SExpr atom)
|
|
| SAtom atom
|
|
| SAtom atom
|
|
| SNil
|
|
| SNil
|
|
- deriving (Eq, Show, Read, Functor)
|
|
|
|
|
|
+ deriving (Eq, Show, Read, Functor, Data)
|
|
|
|
|
|
instance IsString atom => IsString (SExpr atom) where
|
|
instance IsString atom => IsString (SExpr atom) where
|
|
fromString = SAtom . fromString
|
|
fromString = SAtom . fromString
|
|
@@ -33,9 +35,22 @@ instance IsString atom => IsString (SExpr atom) where
|
|
instance IsList (SExpr atom) where
|
|
instance IsList (SExpr atom) where
|
|
type Item (SExpr atom) = SExpr atom
|
|
type Item (SExpr atom) = SExpr atom
|
|
fromList = foldr SCons SNil
|
|
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
|
|
-- level, and we'd rather have the lists themselves
|
|
-- exposed. In this case, we have 'RSList' to
|
|
-- exposed. In this case, we have 'RSList' to
|
|
-- represent a well-formed cons list, and 'RSDotted'
|
|
-- 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 (RSList xs) = foldr SCons SNil (map fromRich xs)
|
|
fromRich (RSDotted xs x) = foldr SCons (SAtom x) (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
|
|
-- | A well-formed s-expression is one which does not
|
|
-- contain any dotted lists. This means that not
|
|
-- contain any dotted lists. This means that not
|
|
-- every value of @SExpr a@ can be converted to a
|
|
-- 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
|
|
instance IsString atom => IsString (WellFormedSExpr atom) where
|
|
fromString = WFSAtom . fromString
|
|
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
|
|
-- | This will be @Nothing@ if the argument contains an
|
|
-- improper list. It should hold that
|
|
-- improper list. It should hold that
|
|
--
|
|
--
|