diff --git a/source/library/Language/Haskell/Brittany/Internal/Transformations/T1_Alt.hs b/source/library/Language/Haskell/Brittany/Internal/Transformations/T1_Alt.hs index 36475d1..9a9a3d7 100644 --- a/source/library/Language/Haskell/Brittany/Internal/Transformations/T1_Alt.hs +++ b/source/library/Language/Haskell/Brittany/Internal/Transformations/T1_Alt.hs @@ -104,7 +104,7 @@ transformAlts = MultiRWSS.withMultiStateA (AltCurPos 0 0 0 False AltLineModeStateNone) . Memo.startEvalMemoT . fmap unwrapBriDocNumbered - . rec + . go where -- this function is exponential by nature and cannot be improved in any -- way i can think of, and i've tried. (stupid StableNames.) @@ -143,25 +143,25 @@ transformAlts = - rec + go :: BriDocNumbered -> Memo.MemoT Int [VerticalSpacing] (MultiRWSS.MultiRWS r w (AltCurPos ': s)) BriDocNumbered - rec bdX@(brDcId, brDc) = do + go bdX@(brDcId, brDc) = do let reWrap = (,) brDcId -- debugAcp :: AltCurPos <- mGet case brDc of -- BDWrapAnnKey annKey bd -> do -- acp <- mGet -- mSet $ acp { _acp_forceMLFlag = altLineModeDecay $ _acp_forceMLFlag acp } - -- BDWrapAnnKey annKey <$> rec bd + -- BDWrapAnnKey annKey <$> go bd BDEmpty{} -> processSpacingSimple bdX $> bdX BDLit{} -> processSpacingSimple bdX $> bdX - BDSeq list -> reWrap . BDSeq <$> list `forM` rec - BDCols sig list -> reWrap . BDCols sig <$> list `forM` rec + BDSeq list -> reWrap . BDSeq <$> list `forM` go + BDCols sig list -> reWrap . BDCols sig <$> list `forM` go BDSeparator -> processSpacingSimple bdX $> bdX BDAddBaseY indent bd -> do acp <- mGet @@ -170,7 +170,7 @@ transformAlts = { _acp_indentPrep = max (_acp_indentPrep acp) indAdd , _acp_indentPrepForced = forced || _acp_indentPrepForced acp } - r <- rec bd + r <- go bd acp' <- mGet mSet $ acp' { _acp_indent = _acp_indent acp } return $ case indent of @@ -181,16 +181,16 @@ transformAlts = BDBaseYPushCur bd -> do acp <- mGet mSet $ acp { _acp_indent = _acp_line acp } - r <- rec bd + r <- go bd acp' <- mGet mSet $ acp' { _acp_indent = _acp_indent acp } return $ reWrap $ BDBaseYPushCur r BDEntryDelta dp bd -> do return $ reWrap $ BDEntryDelta dp bd BDIndentLevelPushCur bd -> do - reWrap . BDIndentLevelPushCur <$> rec bd + reWrap . BDIndentLevelPushCur <$> go bd BDIndentLevelPop bd -> do - reWrap . BDIndentLevelPop <$> rec bd + reWrap . BDIndentLevelPop <$> go bd BDPar indent sameLine indented -> do indAmount <- mAsk <&> _conf_layout .> _lconfig_indentAmount .> confUnpack @@ -207,12 +207,12 @@ transformAlts = { _acp_indent = ind, _acp_indentPrep = 0 , _acp_indentPrepForced = False } - sameLine' <- rec sameLine + sameLine' <- go sameLine mModify $ \acp' -> acp' { _acp_line = ind, _acp_indent = ind , _acp_indentPrepForced = forced } - indented' <- rec indented + indented' <- go indented return $ reWrap $ BDPar indent sameLine' indented' BDAlt [] -> error "empty BDAlt" -- returning BDEmpty instead is a -- possibility, but i will prefer a @@ -222,7 +222,7 @@ transformAlts = altChooser <- mAsk <&> _conf_layout .> _lconfig_altChooser .> confUnpack case altChooser of AltChooserSimpleQuick -> do - rec $ head alts + go $ head alts AltChooserShallowBest -> do spacings <- alts `forM` getSpacing acp <- mGet @@ -245,7 +245,7 @@ transformAlts = <&> \(vs, bd) -> -- trace ("spacing=" ++ show vs ++ ",hasSpace=" ++ show (hasSpace lconf acp vs) ++ ",lineCheck=" ++ show (lineCheck vs)) (hasSpace1 lconf acp vs && lineCheck vs, bd) ) - rec + go $ fromMaybe (-- trace ("choosing last") $ List.last alts) $ Data.List.Extra.firstJust @@ -278,20 +278,20 @@ transformAlts = let checkedOptions :: [Maybe (Int, BriDocNumbered)] = zip [1 ..] options <&> (\(i, (b, x)) -> [ (i, x) | b ]) - rec + go $ fromMaybe (-- trace ("choosing last") $ List.last alts) $ Data.List.Extra.firstJust (fmap snd) checkedOptions BDForceAlt ForceMultiline bd -> do acp <- mGet mSet $ mergeLineMode acp (AltLineModeStateForceML False) - x <- rec bd + x <- go bd mModify $ \acp' -> acp' { _acp_forceMLFlag = _acp_forceMLFlag acp } pure $ x BDForceAlt ForceSingleline bd -> do acp <- mGet mSet $ mergeLineMode acp AltLineModeStateForceSL - x <- rec bd + x <- go bd mModify $ \acp' -> acp' { _acp_forceMLFlag = _acp_forceMLFlag acp } pure $ x BDForwardLineMode bd -> do @@ -299,35 +299,35 @@ transformAlts = mSet $ acp { _acp_forceMLFlag = altLineModeRefresh $ _acp_forceMLFlag acp } - x <- rec bd + x <- go bd mModify $ \acp' -> acp' { _acp_forceMLFlag = _acp_forceMLFlag acp } pure $ x - BDForceAlt ForceZeroAdd bd -> rec bd + BDForceAlt ForceZeroAdd bd -> go bd BDExternal{} -> processSpacingSimple bdX $> bdX BDPlain{} -> processSpacingSimple bdX $> bdX BDQueueComments comms bd -> - reWrap . BDQueueComments comms <$> rec bd + reWrap . BDQueueComments comms <$> go bd BDFlushCommentsPrior loc bd -> -- TODO92 for AnnotationPrior we had this here: -- > acp <- mGet -- > mSet -- > $ acp { _acp_forceMLFlag = altLineModeDecay $ _acp_forceMLFlag acp } - -- > bd' <- rec bd + -- > bd' <- go bd -- not sure if the lineModeDecay is relevant any longer though.. - reWrap . BDFlushCommentsPrior loc <$> rec bd + reWrap . BDFlushCommentsPrior loc <$> go bd BDFlushCommentsPost loc shouldMark bd -> - reWrap . BDFlushCommentsPost loc shouldMark <$> rec bd + reWrap . BDFlushCommentsPost loc shouldMark <$> go bd BDLines [] -> return $ reWrap BDEmpty -- evil transformation. or harmless. BDLines (l : lr) -> do initialAcp <- mGet - l' <- rec l + l' <- go l lr' <- lr `forM` \x -> do mModify $ \acp -> acp { _acp_line = _acp_indent initialAcp , _acp_indent = _acp_indent initialAcp , _acp_indentPrepForced = _acp_indentPrepForced initialAcp } - rec x + go x return $ reWrap $ BDLines (l' : lr') BDEnsureIndent indent bd -> do acp <- mGet @@ -343,7 +343,7 @@ transformAlts = -- Then, the actual indentation is relative to the current -- indentation, not the current cursor position. } - r <- rec bd + r <- go bd acp' <- mGet mSet $ acp' { _acp_indent = _acp_indent acp } return $ case indent of @@ -353,9 +353,9 @@ transformAlts = BrIndentRegularForce -> reWrap $ BDEnsureIndent (BrIndentSpecial indAdd) r BrIndentSpecial i -> reWrap $ BDEnsureIndent (BrIndentSpecial i) r - BDForceAlt (NonBottomSpacing _) bd -> rec bd - BDForceAlt SetParSpacing bd -> rec bd - BDForceAlt ForceParSpacing bd -> rec bd + BDForceAlt (NonBottomSpacing _) bd -> go bd + BDForceAlt SetParSpacing bd -> go bd + BDForceAlt ForceParSpacing bd -> go bd BDDebug s bd -> do acp :: AltCurPos <- mGet tellDebugMess @@ -365,7 +365,7 @@ transformAlts = ++ show brDcId ++ "): acp=" ++ show acp - reWrap . BDDebug s <$> rec bd + reWrap . BDDebug s <$> go bd processSpacingSimple :: ( MonadMultiReader Config m , MonadMultiState AltCurPos m @@ -404,15 +404,15 @@ getSpacing . (MonadMultiReader Config m, MonadMultiWriter (Seq String) m) => BriDocNumbered -> m (LineModeValidity VerticalSpacing) -getSpacing !bridoc = rec bridoc +getSpacing !bridoc = go bridoc where - rec :: BriDocNumbered -> m (LineModeValidity VerticalSpacing) - rec (brDcId, brDc) = do + go :: BriDocNumbered -> m (LineModeValidity VerticalSpacing) + go (brDcId, brDc) = do config <- mAsk let colMax = config & _conf_layout & _lconfig_cols & confUnpack let indAmount = confUnpack $ _lconfig_indentAmount $ _conf_layout $ config result :: LineModeValidity VerticalSpacing <- case brDc of - -- BDWrapAnnKey _annKey bd -> rec bd + -- BDWrapAnnKey _annKey bd -> go bd BDEmpty -> pure $ LineModeValid @@ -421,14 +421,14 @@ getSpacing !bridoc = rec bridoc pure $ LineModeValid $ VerticalSpacing (Text.length t) VerticalSpacingParNone False False - BDSeq list -> sumVs <$> rec `mapM` list - BDCols _sig list -> sumVs <$> rec `mapM` list + BDSeq list -> sumVs <$> go `mapM` list + BDCols _sig list -> sumVs <$> go `mapM` list BDSeparator -> pure $ LineModeValid $ VerticalSpacing 1 VerticalSpacingParNone False False BDAddBaseY indent bd -> do - mVs <- rec bd + mVs <- go bd pure [ vs { _vs_paragraph = case _vs_paragraph vs of @@ -450,7 +450,7 @@ getSpacing !bridoc = rec bridoc , indent == BrIndentNone || _vs_onlyZeroAddInd vs == False ] BDBaseYPushCur bd -> do - mVs <- rec bd + mVs <- go bd return $ mVs <&> \vs -> vs -- We leave par as-is, even though it technically is not -- accurate (in general). @@ -466,11 +466,11 @@ getSpacing !bridoc = rec bridoc ) , _vs_paragraph = VerticalSpacingParSome 0 } - BDIndentLevelPushCur bd -> rec bd - BDIndentLevelPop bd -> rec bd + BDIndentLevelPushCur bd -> go bd + BDIndentLevelPop bd -> go bd BDPar BrIndentNone sameLine indented -> do - mVs <- rec sameLine - mIndSp <- rec indented + mVs <- go sameLine + mIndSp <- go indented return $ [ VerticalSpacing lsp pspResult parFlagResult False -- TODO92 should we turn this on? | VerticalSpacing lsp mPsp _ _ <- mVs @@ -493,21 +493,21 @@ getSpacing !bridoc = rec bridoc ] BDPar{} -> error "BDPar with indent in getSpacing" BDAlt [] -> error "empty BDAlt" - BDAlt (alt : _) -> rec alt + BDAlt (alt : _) -> go alt BDForceAlt ForceMultiline bd -> do - mVs <- rec bd + mVs <- go bd return $ mVs >>= _vs_paragraph .> \case VerticalSpacingParNone -> LineModeInvalid _ -> mVs BDForceAlt ForceSingleline bd -> do - mVs <- rec bd + mVs <- go bd return $ mVs >>= _vs_paragraph .> \case VerticalSpacingParNone -> mVs _ -> LineModeInvalid BDForceAlt ForceZeroAdd bd -> do - mVs <- rec bd + mVs <- go bd pure $ [ vs { _vs_onlyZeroAddInd = True } | vs <- mVs ] - BDForwardLineMode bd -> rec bd + BDForwardLineMode bd -> go bd BDExternal _ txt -> return $ LineModeValid $ case Text.lines txt of [t] -> VerticalSpacing (Text.length t) VerticalSpacingParNone False False @@ -516,10 +516,10 @@ getSpacing !bridoc = rec bridoc [t] -> VerticalSpacing (Text.length t) VerticalSpacingParNone False False _ -> VerticalSpacing 999 VerticalSpacingParNone False False - BDQueueComments _comms bd -> rec bd - BDFlushCommentsPrior _loc bd -> rec bd - BDFlushCommentsPost _loc _shouldMark bd -> rec bd - BDEntryDelta _dp bd -> rec bd + BDQueueComments _comms bd -> go bd + BDFlushCommentsPrior _loc bd -> go bd + BDFlushCommentsPost _loc _shouldMark bd -> go bd + BDEntryDelta _dp bd -> go bd BDLines [] -> pure $ LineModeValid @@ -527,8 +527,8 @@ getSpacing !bridoc = rec bridoc -- TODO92 should we set _vs_onlyZeroAddInd here too? -- did not do that before, but it makes sense for lines.. BDLines (l1 : lR) -> do - mVs <- rec l1 - mVRs <- rec `mapM` lR + mVs <- go l1 + mVRs <- go `mapM` lR let lSps = mVs : mVRs return $ [ VerticalSpacing lsp (VerticalSpacingParSome $ lineMax) False False @@ -538,7 +538,7 @@ getSpacing !bridoc = rec bridoc , lineMax <- getMaxVS $ maxVs $ lSps ] BDEnsureIndent indent bd -> do - mVs <- rec bd + mVs <- go bd let addInd = case indent of BrIndentNone -> 0 BrIndentRegular -> indAmount @@ -547,7 +547,7 @@ getSpacing !bridoc = rec bridoc return $ mVs <&> \(VerticalSpacing lsp psp pf _) -> VerticalSpacing (lsp + addInd) psp pf False BDForceAlt (NonBottomSpacing b) bd -> do - mVs <- rec bd + mVs <- go bd return $ mVs <|> LineModeValid (VerticalSpacing 0 @@ -559,17 +559,17 @@ getSpacing !bridoc = rec bridoc False ) BDForceAlt SetParSpacing bd -> do - mVs <- rec bd + mVs <- go bd return $ mVs <&> \vs -> vs { _vs_parFlag = True } BDForceAlt ForceParSpacing bd -> do - mVs <- rec bd + mVs <- go bd return $ [ vs | vs <- mVs , _vs_parFlag vs || _vs_paragraph vs == VerticalSpacingParNone ] BDDebug s bd -> do - r <- rec bd + r <- go bd tellDebugMess $ "getSpacing: BDDebug " ++ show s @@ -604,9 +604,9 @@ getSpacing !bridoc = rec bridoc (LineModeValid $ VerticalSpacing 0 VerticalSpacingParNone False False) sumVs :: [LineModeValidity VerticalSpacing] -> LineModeValidity VerticalSpacing - sumVs sps = foldl' (liftM2 go) initial sps + sumVs sps = foldl' (liftM2 goSum) initial sps where - go (VerticalSpacing x1 x2 x3 x4) (VerticalSpacing y1 y2 _ y4) = + goSum (VerticalSpacing x1 x2 x3 x4) (VerticalSpacing y1 y2 _ y4) = VerticalSpacing (x1 + y1) (case (x2, y2) of @@ -646,7 +646,7 @@ getSpacings => Int -> BriDocNumbered -> Memo.MemoT Int [VerticalSpacing] m [VerticalSpacing] -getSpacings limit bridoc = preFilterLimit <$> rec bridoc +getSpacings limit bridoc = preFilterLimit <$> go bridoc where -- when we do `take K . filter someCondition` on a list of spacings, we -- need to first (also) limit the size of the input list, otherwise a @@ -657,8 +657,8 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc preFilterLimit = take (3 * limit) memoWithKey :: Memo.MonadMemo k v m1 => k -> m1 v -> m1 v memoWithKey k v = Memo.memo (const v) k - rec :: BriDocNumbered -> Memo.MemoT Int [VerticalSpacing] m [VerticalSpacing] - rec (brDcId, brdc) = memoWithKey brDcId $ do + go :: BriDocNumbered -> Memo.MemoT Int [VerticalSpacing] m [VerticalSpacing] + go (brDcId, brdc) = memoWithKey brDcId $ do config <- mAsk let colMax = config & _conf_layout & _lconfig_cols & confUnpack let @@ -686,14 +686,14 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc -- smallest member of this "equal group". specialNub :: [VerticalSpacing] -> [VerticalSpacing] specialNub [] = [] - specialNub (x1 : xr) = case go x1 xr of + specialNub (x1 : xr) = case goNub x1 xr of (r, xs') -> r : specialNub xs' where - go y1 [] = (y1, []) - go y1 (y2 : yr) = case specialCompare y1 y2 of - Unequal -> let (r, yr') = go y1 yr in (r, y2 : yr') - Smaller -> go y1 yr - Bigger -> go y2 yr + goNub y1 [] = (y1, []) + goNub y1 (y2 : yr) = case specialCompare y1 y2 of + Unequal -> let (r, yr') = goNub y1 yr in (r, y2 : yr') + Smaller -> goNub y1 yr + Bigger -> goNub y2 yr let -- the standard function used to enforce a constant upper bound -- on the number of elements returned for each node. Should be -- applied whenever in a parent the combination of spacings from @@ -731,17 +731,17 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc -- total. . preFilterLimit result <- case brdc of - -- BDWrapAnnKey _annKey bd -> rec bd + -- BDWrapAnnKey _annKey bd -> go bd BDEmpty -> return $ [VerticalSpacing 0 VerticalSpacingParNone False False] BDLit t -> do let l = Text.length t pure $ [VerticalSpacing l VerticalSpacingParNone False False] - BDSeq list -> fmap sumVs . mapM filterAndLimit <$> rec `mapM` list - BDCols _sig list -> fmap sumVs . mapM filterAndLimit <$> rec `mapM` list + BDSeq list -> fmap sumVs . mapM filterAndLimit <$> go `mapM` list + BDCols _sig list -> fmap sumVs . mapM filterAndLimit <$> go `mapM` list BDSeparator -> pure $ [VerticalSpacing 1 VerticalSpacingParNone False False] BDAddBaseY indent bd -> do - mVs <- rec bd + mVs <- go bd return $ mVs <&> \vs -> vs { _vs_paragraph = case _vs_paragraph vs of VerticalSpacingParNone -> VerticalSpacingParNone @@ -758,7 +758,7 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc BrIndentSpecial j -> i + j } BDBaseYPushCur bd -> do - mVs <- rec bd + mVs <- go bd return $ mVs <&> \vs -> vs -- We leave par as-is, even though it technically is not -- accurate (in general). @@ -777,11 +777,11 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc VerticalSpacingParSome i -> VerticalSpacingParSome i VerticalSpacingParAlways i -> VerticalSpacingParAlways i } - BDIndentLevelPushCur bd -> rec bd - BDIndentLevelPop bd -> rec bd + BDIndentLevelPushCur bd -> go bd + BDIndentLevelPop bd -> go bd BDPar BrIndentNone sameLine indented -> do - mVss <- filterAndLimit <$> rec sameLine - indSps <- filterAndLimit <$> rec indented + mVss <- filterAndLimit <$> go sameLine + indSps <- filterAndLimit <$> go indented let mVsIndSp = take limit $ [ (x, y) | x <- mVss, y <- indSps ] return $ mVsIndSp <&> \(VerticalSpacing lsp mPsp _ _, indSp) -> VerticalSpacing @@ -803,17 +803,17 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc BDPar{} -> error "BDPar with indent in getSpacing" BDAlt [] -> error "empty BDAlt" - -- BDAlt (alt:_) -> rec alt + -- BDAlt (alt:_) -> go alt BDAlt alts -> do - r <- rec `mapM` alts + r <- go `mapM` alts return $ filterAndLimit =<< r BDForceAlt ForceMultiline bd -> do - mVs <- filterAndLimit <$> rec bd + mVs <- filterAndLimit <$> go bd return $ filter ((/= VerticalSpacingParNone) . _vs_paragraph) mVs BDForceAlt ForceSingleline bd -> do - mVs <- filterAndLimit <$> rec bd + mVs <- filterAndLimit <$> go bd return $ filter ((== VerticalSpacingParNone) . _vs_paragraph) mVs - BDForwardLineMode bd -> rec bd + BDForwardLineMode bd -> go bd BDExternal _ txt | [t] <- Text.lines txt -> do let l = Text.length t pure $ [VerticalSpacing l VerticalSpacingParNone False False] @@ -830,10 +830,10 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc VerticalSpacing (tl t1) (VerticalSpacingParAlways 0) True False | allowHangingQuasiQuotes ] - BDQueueComments _comms bd -> rec bd - BDFlushCommentsPrior _loc bd -> rec bd - BDFlushCommentsPost _loc _shouldMark bd -> rec bd - BDEntryDelta _dp bd -> rec bd + BDQueueComments _comms bd -> go bd + BDFlushCommentsPrior _loc bd -> go bd + BDFlushCommentsPost _loc _shouldMark bd -> go bd + BDEntryDelta _dp bd -> go bd BDLines [] -> pure $ [VerticalSpacing 0 VerticalSpacingParNone False False] BDLines ls@(_ : _) -> do @@ -842,7 +842,7 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc -- paragraph". That most importantly means that Lines should never -- be inserted anywhere but at the start of the line. A -- counterexample would be anything like Seq[Lit "foo", Lines]. - lSpss <- map filterAndLimit <$> rec `mapM` ls + lSpss <- mapM (fmap filterAndLimit . go) ls let worbled = sequence $ case lSpss of [] -> [] @@ -858,7 +858,7 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc $ "should not happen. if my logic does not fail" ++ "me, this follows from not (null ls)." return $ sumF <$> worbled - -- lSpss@(mVs:_) <- rec `mapM` ls + -- lSpss@(mVs:_) <- go `mapM` ls -- return $ case Control.Lens.transposeOf traverse lSpss of -- TODO: we currently only -- -- consider the first alternative for the -- -- line's spacings. @@ -870,7 +870,7 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc -- (lSps:_) -> mVs <&> \(VerticalSpacing lsp _) -> -- VerticalSpacing lsp $ VerticalSpacingParSome $ getMaxVS $ maxVs lSps BDEnsureIndent indent bd -> do - mVs <- rec bd + mVs <- go bd let addInd = case indent of BrIndentNone -> 0 @@ -884,7 +884,7 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc -- all tests work without it. It should be possible to have -- `spMakePar` map VSPAlways{} to VSPSome x1, which fixes this -- problem but breaks certain other cases. - mVs <- rec bd + mVs <- go bd return $ if null mVs then [ VerticalSpacing @@ -936,20 +936,20 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc -- mVs -- ] BDForceAlt SetParSpacing bd -> do - mVs <- rec bd + mVs <- go bd return $ mVs <&> \vs -> vs { _vs_parFlag = True } BDForceAlt ForceParSpacing bd -> do - mVs <- preFilterLimit <$> rec bd + mVs <- preFilterLimit <$> go bd return $ [ vs | vs <- mVs , _vs_parFlag vs || _vs_paragraph vs == VerticalSpacingParNone ] BDForceAlt ForceZeroAdd bd -> do - mVs <- preFilterLimit <$> rec bd + mVs <- preFilterLimit <$> go bd pure [ vs { _vs_onlyZeroAddInd = True } | vs <- mVs ] BDDebug s bd -> do - r <- rec bd + r <- go bd tellDebugMess $ "getSpacings: BDDebug " ++ show s @@ -980,9 +980,9 @@ getSpacings limit bridoc = preFilterLimit <$> rec bridoc ) (VerticalSpacing 0 VerticalSpacingParNone False False) sumVs :: [VerticalSpacing] -> VerticalSpacing - sumVs sps = foldl' go initial sps + sumVs sps = foldl' goSum initial sps where - go (VerticalSpacing x1 x2 x3 x4) (VerticalSpacing y1 y2 _ y4) = + goSum (VerticalSpacing x1 x2 x3 x4) (VerticalSpacing y1 y2 _ y4) = VerticalSpacing (x1 + y1) (case (x2, y2) of