aboutsummaryrefslogtreecommitdiff
path: root/ch05/Prettify.hs
diff options
context:
space:
mode:
authorJan Sucan <jan@jansucan.com>2023-03-28 17:09:27 +0200
committerJan Sucan <jan@jansucan.com>2023-04-10 16:52:19 +0200
commit2c4e32dbcd6a74a93d6121212c5a44461160a38f (patch)
tree2640fd4b4218787bb7b7ac93f52b63933b4da38a /ch05/Prettify.hs
parent742195819304c1e009fa20a8c6f387f61d1975fd (diff)
ch05: Copy needed files from the examples
Diffstat (limited to 'ch05/Prettify.hs')
-rw-r--r--ch05/Prettify.hs160
1 files changed, 160 insertions, 0 deletions
diff --git a/ch05/Prettify.hs b/ch05/Prettify.hs
new file mode 100644
index 0000000..7b3ea10
--- /dev/null
+++ b/ch05/Prettify.hs
@@ -0,0 +1,160 @@
+module Prettify
+ (
+ -- * Constructors
+ Doc
+ -- * Basic combinators
+ , (<>)
+ , empty
+ , char
+ , text
+ , line
+ -- * Derived combinators
+ , double
+ , fsep
+ , hcat
+ , punctuate
+ -- * Renderers
+ , compact
+ , pretty
+ ) where
+
+{--
+import Data.Monoid (Monoid(..))
+
+instance Monoid Doc where
+ mempty = empty
+ mappend = (<>)
+--}
+
+{-- snippet Doc --}
+data Doc = Empty
+ | Char Char
+ | Text String
+ | Line
+ | Concat Doc Doc
+ | Union Doc Doc
+ deriving (Show,Eq)
+{-- /snippet Doc --}
+
+{-- snippet append --}
+(<>) :: Doc -> Doc -> Doc
+Empty <> y = y
+x <> Empty = x
+x <> y = x `Concat` y
+{-- /snippet append --}
+
+{-- snippet basic --}
+empty :: Doc
+empty = Empty
+
+char :: Char -> Doc
+char c = Char c
+
+text :: String -> Doc
+text "" = Empty
+text s = Text s
+
+double :: Double -> Doc
+double d = text (show d)
+{-- /snippet basic --}
+
+{-- snippet line --}
+line :: Doc
+line = Line
+{-- /snippet line --}
+
+{-- snippet hcat --}
+hcat :: [Doc] -> Doc
+hcat = fold (<>)
+
+fold :: (Doc -> Doc -> Doc) -> [Doc] -> Doc
+fold f = foldr f empty
+{-- /snippet hcat --}
+
+{-- snippet fsep --}
+fsep :: [Doc] -> Doc
+fsep = fold (</>)
+
+(</>) :: Doc -> Doc -> Doc
+x </> y = x <> softline <> y
+
+softline :: Doc
+softline = group line
+{-- /snippet fsep --}
+
+{-- snippet group --}
+group :: Doc -> Doc
+group x = flatten x `Union` x
+{-- /snippet group --}
+
+{-- snippet flatten --}
+flatten :: Doc -> Doc
+flatten (x `Concat` y) = flatten x `Concat` flatten y
+flatten Line = Char ' '
+flatten (x `Union` _) = flatten x
+flatten other = other
+{-- /snippet flatten --}
+
+{-- snippet punctuate --}
+punctuate :: Doc -> [Doc] -> [Doc]
+punctuate p [] = []
+punctuate p [d] = [d]
+punctuate p (d:ds) = (d <> p) : punctuate p ds
+{-- /snippet punctuate --}
+
+{-- snippet compact --}
+compact :: Doc -> String
+compact x = transform [x]
+ where transform [] = ""
+ transform (d:ds) =
+ case d of
+ Empty -> transform ds
+ Char c -> c : transform ds
+ Text s -> s ++ transform ds
+ Line -> '\n' : transform ds
+ a `Concat` b -> transform (a:b:ds)
+ _ `Union` b -> transform (b:ds)
+{-- /snippet compact --}
+
+{-- snippet pretty.type --}
+pretty :: Int -> Doc -> String
+{-- /snippet pretty.type --}
+
+{-- snippet pretty --}
+pretty width x = best 0 [x]
+ where best col (d:ds) =
+ case d of
+ Empty -> best col ds
+ Char c -> c : best (col + 1) ds
+ Text s -> s ++ best (col + length s) ds
+ Line -> '\n' : best 0 ds
+ a `Concat` b -> best col (a:b:ds)
+ a `Union` b -> nicest col (best col (a:ds))
+ (best col (b:ds))
+ best _ _ = ""
+
+ nicest col a b | (width - least) `fits` a = a
+ | otherwise = b
+ where least = min width col
+{-- /snippet pretty --}
+
+{-- snippet fits --}
+fits :: Int -> String -> Bool
+w `fits` _ | w < 0 = False
+w `fits` "" = True
+w `fits` ('\n':_) = True
+w `fits` (c:cs) = (w - 1) `fits` cs
+{-- /snippet fits --}
+
+{-- snippet nest --}
+nest :: Int -> Doc -> Doc
+{-- /snippet nest --}
+nest = undefined
+
+{-- snippet fill --}
+fill :: Int -> Doc -> Doc
+{-- /snippet fill --}
+fill = undefined
+
+--instance Show Doc where
+-- show doc = pretty 80 doc