Put tree drawing logic in a separate module with a class type
This commit is contained in:
parent
98c06b95ce
commit
5d1907094d
3 changed files with 49 additions and 27 deletions
|
@ -20,9 +20,11 @@ extra-source-files: CHANGELOG.md
|
||||||
library
|
library
|
||||||
exposed-modules: Graph
|
exposed-modules: Graph
|
||||||
, Stream
|
, Stream
|
||||||
|
, Tree
|
||||||
-- other-modules:
|
-- other-modules:
|
||||||
-- other-extensions:
|
-- other-extensions:
|
||||||
build-depends: base >=4.9 && <4.13
|
build-depends: base >=4.9 && <4.13
|
||||||
, containers
|
, containers
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
|
ghc-options: -Wall
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
|
@ -1,21 +1,31 @@
|
||||||
module Stream (
|
module Stream (
|
||||||
Stream(..)
|
Stream(..)
|
||||||
|
, append
|
||||||
|
, empty
|
||||||
, fromList
|
, fromList
|
||||||
, infinite
|
, infinite
|
||||||
, merge
|
, merge
|
||||||
, showStream
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.List (intercalate)
|
import Tree (Tree(..), Structure(..))
|
||||||
|
|
||||||
data Stream a = Stream [(a, Stream a)] deriving Show
|
data Stream a = Stream [(a, Stream a)] deriving Show
|
||||||
|
|
||||||
|
instance Functor Stream where
|
||||||
|
fmap f (Stream pairs) =
|
||||||
|
Stream $ (\(a, stream) -> (f a, fmap f stream)) <$> pairs
|
||||||
|
|
||||||
|
instance Tree Stream where
|
||||||
|
getStructure (Stream pairs) =
|
||||||
|
Node $ (\(s, stream) -> (s, getStructure stream)) <$> pairs
|
||||||
|
|
||||||
empty :: Stream a
|
empty :: Stream a
|
||||||
empty = fromList []
|
empty = fromList []
|
||||||
|
|
||||||
append :: Stream a -> Stream a -> Stream a
|
append :: Stream a -> Stream a -> Stream a
|
||||||
append (Stream []) b = b
|
append (Stream []) b = b
|
||||||
append (Stream pairs) b = Stream $ (\(a, stream) -> (a, stream `append` b)) <$> pairs
|
append (Stream pairs) b =
|
||||||
|
Stream $ (\(a, stream) -> (a, stream `append` b)) <$> pairs
|
||||||
|
|
||||||
fromList :: [a] -> Stream a
|
fromList :: [a] -> Stream a
|
||||||
fromList [] = Stream []
|
fromList [] = Stream []
|
||||||
|
@ -35,27 +45,3 @@ merge (Stream aPairs) (Stream bPairs) = Stream $ foldl mergeOrAdd aPairs bPairs
|
||||||
case openAt ((== b) . fst) [] accumulator of
|
case openAt ((== b) . fst) [] accumulator of
|
||||||
(up, []) -> (up, [(b, bStream)])
|
(up, []) -> (up, [(b, bStream)])
|
||||||
(up, (x, xStream):down) -> (up, (x, merge xStream bStream):down)
|
(up, (x, xStream):down) -> (up, (x, merge xStream bStream):down)
|
||||||
|
|
||||||
showStream :: Show a => Stream a -> String
|
|
||||||
showStream = intercalate "\n" . getLines
|
|
||||||
|
|
||||||
getLines :: Show a => Stream a -> [String]
|
|
||||||
getLines (Stream []) = ["╼"]
|
|
||||||
getLines (Stream [(a, stream)]) = showBlock '─' (a, stream)
|
|
||||||
getLines (Stream ((a, stream):pairs)) = concat $
|
|
||||||
showBlock '┬' (a, stream) : showBlocks pairs
|
|
||||||
where
|
|
||||||
showBlocks [] = []
|
|
||||||
showBlocks [(a, stream)] = [showBlock '╰' (a, stream)]
|
|
||||||
showBlocks ((a, stream):pairs) =
|
|
||||||
showBlock '├' (a, stream) : showBlocks pairs
|
|
||||||
|
|
||||||
showBlock :: Show a => Char -> (a, Stream a) -> [String]
|
|
||||||
showBlock connectingChar (a, stream) =
|
|
||||||
case getLines stream of
|
|
||||||
[] -> []
|
|
||||||
firstLine:otherLines -> (prefix ++ firstLine) : (pad <$> otherLines)
|
|
||||||
where
|
|
||||||
connect = ((if connectingChar `elem` "├┬" then '│' else ' '):)
|
|
||||||
prefix = connectingChar : " " ++ show a ++ " "
|
|
||||||
pad = connect . (take (length prefix - 1) (repeat ' ') ++)
|
|
||||||
|
|
34
src/Tree.hs
Normal file
34
src/Tree.hs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
module Tree (
|
||||||
|
Tree(..)
|
||||||
|
, Structure(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
data Structure = Node [(String, Structure)]
|
||||||
|
|
||||||
|
class Functor a => Tree a where
|
||||||
|
getStructure :: a String -> Structure
|
||||||
|
|
||||||
|
draw :: Show b => a b -> String
|
||||||
|
draw = unlines . getLines . getStructure . fmap show
|
||||||
|
|
||||||
|
getLines :: Structure -> [String]
|
||||||
|
getLines (Node []) = ["╼"]
|
||||||
|
getLines (Node [(s, structure)]) = showBlock '─' (s, structure)
|
||||||
|
getLines (Node ((s, structure):pairs)) = concat $
|
||||||
|
showBlock '┬' (s, structure) : showBlocks pairs
|
||||||
|
|
||||||
|
showBlocks :: [(String, Structure)] -> [[String]]
|
||||||
|
showBlocks [] = []
|
||||||
|
showBlocks [(s, structure)] = [showBlock '╰' (s, structure)]
|
||||||
|
showBlocks ((s, structure):pairs) =
|
||||||
|
showBlock '├' (s, structure) : showBlocks pairs
|
||||||
|
|
||||||
|
showBlock :: Char -> (String, Structure) -> [String]
|
||||||
|
showBlock connectingChar (s, structure) =
|
||||||
|
case getLines structure of
|
||||||
|
[] -> []
|
||||||
|
firstLine:otherLines -> (prefix ++ firstLine) : (pad <$> otherLines)
|
||||||
|
where
|
||||||
|
connect = ((if connectingChar `elem` "├┬" then '│' else ' '):)
|
||||||
|
prefix = connectingChar : " " ++ s ++ " "
|
||||||
|
pad = connect . (take (length prefix - 1) (repeat ' ') ++)
|
Loading…
Reference in a new issue