diff --git a/posts/number-number/2/Diagonal.hs b/posts/number-number/2/Diagonal.hs index d69e52e..9b223d5 100644 --- a/posts/number-number/2/Diagonal.hs +++ b/posts/number-number/2/Diagonal.hs @@ -14,25 +14,27 @@ instance Show RowNumber where -- Rendered cell data, along with its row number and an optional value to show instead data RenderCell a = RC { - cellRow :: Maybe RowNumber, - cellForceShow :: Maybe String, - cellData :: a + cellRow :: Maybe RowNumber, -- Nothing if this is a header; Just . RC otherwise + cellForceShow :: Maybe String, -- TODO: Either String a + cellData :: Maybe a } deriving Functor -- If a forced value is availaible, use it; otherwise, show the inside instance Show a => Show (RenderCell a) where - show (RC _ Nothing x) = show x - show (RC _ (Just s) _) = s + show (RC _ Nothing (Just x)) = show x + show (RC _ Nothing Nothing) = "" + show (RC _ (Just s) _) = s -- Lift a RenderCell over Either to an Either over RenderCells --- If the force-string is set, then a `Left` version with an undefined value is returned +-- If the force-string is set, then a `Left` version with a Nothing value is returned liftRC :: RenderCell (Either a b) -> Either (RenderCell a) (RenderCell b) -liftRC (RC rn (Just x) _) = Left $ RC rn (Just x) undefined -liftRC (RC rn Nothing (Left v)) = Left $ RC rn Nothing v -liftRC (RC rn Nothing (Right v)) = Right $ RC rn Nothing v +liftRC (RC rn Nothing Nothing) = Left $ RC rn Nothing Nothing +liftRC (RC rn (Just x) _) = Left $ RC rn (Just x) Nothing +liftRC (RC rn Nothing (Just (Left v))) = Left $ RC rn Nothing $ Just v +liftRC (RC rn Nothing (Just (Right v))) = Right $ RC rn Nothing $ Just v -- Single column with a fixed header and data coming from a row number -newColumn header f = columns f (\_ -> Headed $ RC Nothing (Just header) undefined) [()] +newColumn header f = columns f (\_ -> Headed $ RC Nothing (Just header) Nothing) [()] -- Numbered rows of data, as opposed to data for rendering data DiagRow a = DR { @@ -42,7 +44,7 @@ data DiagRow a = DR { -- Same as `newColumn`, but reads into a DiagRow's row numberRows -- The display function `f` is used to convert the value to a String -newColumnR header f = newColumn header (\_ c -> RC (Just $ rowNumber c) (Just $ f $ rowNumber c) undefined) +newColumnR header f = newColumn header (\_ c -> RC (Just $ rowNumber c) (Just $ f $ rowNumber c) Nothing) -- Number rows with the title "Sequence" numberColumn = newColumnR "Sequence" show @@ -53,9 +55,9 @@ ellipsisColumn = newColumnR "..." (const "...") -- The ellipsis row is mapped to a cells which always display as ellipses -- The remaining rows are `Right` if they lie on the main diagonal, or `Left` otherwise diagBox' n = columns cell headCell [0..n] - where cell _ (DR Ellipsis _) = RC (Just Ellipsis) (Just "...") undefined - cell i (DR rn rd) = RC (Just rn) Nothing $ (if RN i == rn then Right else Left) (rd !! i) - headCell i = Headed $ RC Nothing (Just $ show i) undefined + where cell _ (DR Ellipsis _) = RC (Just Ellipsis) (Just "...") Nothing + cell i (DR rn rd) = RC (Just rn) Nothing $ Just $ (if RN i == rn then Right else Left) (rd !! i) + headCell i = Headed $ RC Nothing (Just $ show i) Nothing diagBox n = numberColumn <> diagBox' n <> ellipsisColumn @@ -71,6 +73,15 @@ displayRows f = (displayTable .) . tagRows' rowsOmega :: [[a]] -> [a] -> [DiagRow a] rowsOmega xs y = zipWith (\x n -> DR (RN n) x) xs [0..] ++ [DR Ellipsis [], DR Omega y] +diagData = rowsOmega [ + [1, 2, 3, 4, 5, 6], + [9, 2, 4, 8, 3, 7], + [2, 2, 8, 2, 2, 2], + [2, 3, 9, 3, 9, 9], + [9, 4, 9, 4, 9, 4], + [8, 1, 2, 5, 7, 9] + ] + [2, 3, 9, 4, 0, 0] displayDiagTable ps = rmap style . diagBox where style = either show id . displayRows (("Red " ++) . show) (map (, ("Green " ++). show) ps)