-- Generate appendTree<0..4> and addDigits<1..4> for Data.Sequence
module Main where
main :: IO ()
main = putStr (compose [showAppend n | n <- [0..4]] "")
showAppend :: Int -> ShowS
showAppend n =
showChar '\n' .
showString "appendTree" . shows n . showString " :: " .
showFunType
([fingertree] ++ replicate n tyarg ++ [fingertree]) fingertree .
showString "\n" .
appendTreeClause "EmptyT" "xs" (showCons (args n) (showString "xs")) .
appendTreeClause "xs" "EmptyT" (showSnoc (showString "xs") (args n)) .
appendTreeClause "(Single x)" "xs"
(showCons ('x':args n) (showString "xs")) .
appendTreeClause "xs" "(Single x)"
(showSnoc (showString "xs") (args n++"x")) .
appendTreeClause "(Deep s1 pr1 m1 sf1)" "(Deep s2 pr2 m2 sf2)"
(showString "Deep (s1" .
compose [showString " + size " . showChar v | v <- args n] .
showString " + s2) pr1 (addDigits" . shows n .
showString " m1 sf1" . showArgList (args n) .
showString " pr2 m2) sf2") .
showChar '\n' .
showString "addDigits" . shows n . showString " :: " .
showFunType
([fingertree_node, digit] ++ replicate n tyarg ++ [digit, fingertree_node])
fingertree_node .
showString "\n" .
compose [addDigitsClause n1 n2 | n1 <- [1..4], n2 <- [1..4]]
where
fingertree = tyapp "FingerTree" tyarg
digit = tyapp "Digit" tyarg
fingertree_node = tyapp "FingerTree" (tyapp "Node" tyarg)
showFunType ts tr =
compose [showString t . showString " -> " | t <- ts] . showString tr
tyapp tc t = tc ++ " (" ++ t ++ ")"
tyarg
| n == 0 = "Elem a"
| otherwise = "Node a"
appendTreeClause t1 t2 rhs =
showString "appendTree" . shows n .
showChar ' ' . showString t1 . showArgList (args n) .
showChar ' ' . showString t2 .
showString " =\n " . rhs . showChar '\n'
addDigitsClause n1 n2 =
showString "addDigits" . shows n .
showString " m1 (" . showDigit vs1 . showChar ')' .
showArgList vsm .
showString " (" . showDigit vs2 . showString ") m2" .
showString " =\n " .
showString "appendTree" . shows (length ns) .
showString " m1" .
compose [showString " (" . showNode node . showChar ')' |
node <- ns] .
showString " m2" . showChar '\n'
where
vs = args (n1+n+n2)
vs1 = take n1 vs
vsm = take n (drop n1 vs)
vs2 = drop (n1+n) vs
ns = nodes vs
data Node a = Node2 a a | Node3 a a a
nodes :: [a] -> [Node a]
nodes [a, b] = [Node2 a b]
nodes [a, b, c] = [Node3 a b c]
nodes [a, b, c, d] = [Node2 a b, Node2 c d]
nodes (a:b:c:xs) = Node3 a b c : nodes xs
showNode (Node2 a b) =
showString "node2 " . showChar a . showChar ' ' . showChar b
showNode (Node3 a b c) =
showString "node3 " . showChar a . showChar ' ' . showChar b .
showChar ' ' . showChar c
showDigit vs =
showString (["One", "Two", "Three", "Four"]!!(length vs-1)) .
showArgList vs
showArgList :: [Char] -> ShowS
showArgList vs = compose [showChar ' ' . showChar c | c <- vs]
args :: Int -> [Char]
args n = take n ['a'..]
showCons xs sf =
compose [showChar x . showString " `consTree` " | x <- xs] . sf
showSnoc sf xs =
sf . compose [showString " `snocTree` " . showChar x | x <- xs]
compose :: [a -> a] -> a -> a
compose = flip (foldr id)