Repr.hs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. module Data.SCargot.Repr
  2. ( SExpr(..)
  3. , RichSExpr(..)
  4. , toRich
  5. , fromRich
  6. , WellFormedSExpr(..)
  7. , toWellFormed
  8. , fromWellFormed
  9. ) where
  10. -- | All S-Expressions can be understood as a sequence
  11. -- of @cons@ cells (represented here by 'SCons'), the
  12. -- empty list @nil@ (represented by 'SNil') or an
  13. -- @atom@.
  14. data SExpr atom
  15. = SCons (SExpr atom) (SExpr atom)
  16. | SAtom atom
  17. | SNil
  18. deriving (Eq, Show, Read)
  19. -- | Sometimes, the cons-based interface is too low
  20. -- level, and we'd rather have the lists themselves
  21. -- exposed. In this case, we have 'RSList' to
  22. -- represent a well-formed cons list, and 'RSDotted'
  23. -- to represent an improper list of the form
  24. -- @(a b c . d)@.
  25. data RichSExpr atom
  26. = RSList [RichSExpr atom]
  27. | RSDotted [RichSExpr atom] atom
  28. | RSAtom atom
  29. deriving (Eq, Show, Read)
  30. -- | A Rich S-Expression might be a nicer interface
  31. -- for certain libraries. It should always be true
  32. -- that
  33. --
  34. -- > fromRich . toRich == id
  35. --
  36. -- and that
  37. --
  38. -- > toRich . fromRich == id
  39. toRich :: SExpr atom -> RichSExpr atom
  40. toRich (SAtom a) = RSAtom a
  41. toRich (SCons x xs) = go xs [toRich x]
  42. where go (SAtom a) rs = RSDotted rs a
  43. go SNil rs = RSList rs
  44. go (SCons x xs) rs = go xs (toRich x:rs)
  45. -- | This follows the same laws as 'toRich'.
  46. fromRich :: RichSExpr atom -> SExpr atom
  47. fromRich (RSAtom a) = SAtom a
  48. fromRich (RSList xs) = foldr SCons SNil (map fromRich xs)
  49. fromRich (RSDotted xs x) = foldr SCons (SAtom x) (map fromRich xs)
  50. -- | A well-formed s-expression is one which does not
  51. -- contain any dotted lists. This means that not
  52. -- every value of @SExpr a@ can be converted to a
  53. -- @WellFormedSExpr a@, although the opposite is
  54. -- fine.
  55. data WellFormedSExpr atom
  56. = WFSList [WellFormedSExpr atom]
  57. | WFSAtom atom
  58. deriving (Eq, Show, Read)
  59. -- | This will be @Nothing@ is the argument contains an
  60. -- improper list. It should hold that
  61. --
  62. -- > toWellFormed . fromWellFormed == Right
  63. toWellFormed :: SExpr atom -> Either String (WellFormedSExpr atom)
  64. toWellFormed (SAtom a) = return (WFSAtom a)
  65. toWellFormed (SCons x xs) = do
  66. x' <- toWellFormed x
  67. go xs [x']
  68. where go (SAtom a) rs = Left "Found atom in cdr position"
  69. go SNil rs = return (WFSList rs)
  70. go (SCons x xs) rs = do
  71. x' <- toWellFormed x
  72. go xs (x':rs)
  73. -- | Convert a WellFormedSExpr back into a SExpr.
  74. fromWellFormed :: WellFormedSExpr atom -> SExpr atom
  75. fromWellFormed (WFSAtom a) = SAtom a
  76. fromWellFormed (WFSList xs) =
  77. foldr SCons SNil (map fromWellFormed xs)