{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module Text.Pandoc.Parsing.GridTable
( gridTableWith
, gridTableWith'
, tableWith
, tableWith'
, widthsFromIndices
, TableComponents (..)
, TableNormalization (..)
, toTableComponents
, toTableComponents'
)
where
import Data.Array (elems)
import Data.Text (Text)
import Safe (lastDef)
import Text.Pandoc.Options (ReaderOptions (readerColumns))
import Text.Pandoc.Builder (Blocks)
import Text.Pandoc.Definition
import Text.Pandoc.Parsing.Capabilities
import Text.Pandoc.Parsing.General
import Text.Pandoc.Sources
import Text.Parsec (Stream (..), ParsecT, optional, sepEndBy1, try)
import qualified Data.Text as T
import qualified Text.GridTable as GT
import qualified Text.Pandoc.Builder as B
data TableComponents = TableComponents
{ TableComponents -> Attr
tableAttr :: Attr
, TableComponents -> Caption
tableCaption :: Caption
, TableComponents -> [ColSpec]
tableColSpecs :: [ColSpec]
, TableComponents -> TableHead
tableHead :: TableHead
, TableComponents -> [TableBody]
tableBodies :: [TableBody]
, :: TableFoot
}
tableFromComponents :: TableComponents -> Blocks
tableFromComponents :: TableComponents -> Blocks
tableFromComponents (TableComponents Attr
attr Caption
capt [ColSpec]
colspecs TableHead
th [TableBody]
tb TableFoot
tf) =
Attr
-> Caption
-> [ColSpec]
-> TableHead
-> [TableBody]
-> TableFoot
-> Blocks
B.tableWith Attr
attr Caption
capt [ColSpec]
colspecs TableHead
th [TableBody]
tb TableFoot
tf
toTableComponents :: [Alignment] -> [Double] -> [Blocks] -> [[Blocks]]
-> TableComponents
toTableComponents :: [Alignment]
-> [Double] -> [Blocks] -> [[Blocks]] -> TableComponents
toTableComponents = TableNormalization
-> [Alignment]
-> [Double]
-> [Blocks]
-> [[Blocks]]
-> TableComponents
toTableComponents' TableNormalization
NoNormalization
toTableComponents' :: TableNormalization
-> [Alignment] -> [Double] -> [Blocks] -> [[Blocks]]
-> TableComponents
toTableComponents' :: TableNormalization
-> [Alignment]
-> [Double]
-> [Blocks]
-> [[Blocks]]
-> TableComponents
toTableComponents' TableNormalization
normalization [Alignment]
aligns [Double]
widths [Blocks]
heads [[Blocks]]
rows =
let th :: TableHead
th = Attr -> [Row] -> TableHead
TableHead Attr
nullAttr (TableNormalization -> [Blocks] -> [Row]
toHeaderRow TableNormalization
normalization [Blocks]
heads)
tb :: TableBody
tb = Attr -> RowHeadColumns -> [Row] -> [Row] -> TableBody
TableBody Attr
nullAttr RowHeadColumns
0 [] (forall a b. (a -> b) -> [a] -> [b]
map [Blocks] -> Row
toRow [[Blocks]]
rows)
tf :: TableFoot
tf = Attr -> [Row] -> TableFoot
TableFoot Attr
nullAttr []
colspecs :: [ColSpec]
colspecs = [Alignment] -> [Double] -> [ColSpec]
toColSpecs [Alignment]
aligns [Double]
widths
in Attr
-> Caption
-> [ColSpec]
-> TableHead
-> [TableBody]
-> TableFoot
-> TableComponents
TableComponents Attr
nullAttr Caption
B.emptyCaption [ColSpec]
colspecs TableHead
th [TableBody
tb] TableFoot
tf
toColSpecs :: [Alignment]
-> [Double]
-> [ColSpec]
toColSpecs :: [Alignment] -> [Double] -> [ColSpec]
toColSpecs [Alignment]
aligns [Double]
widths = forall a b. [a] -> [b] -> [(a, b)]
zip [Alignment]
aligns (forall a b. (a -> b) -> [a] -> [b]
map Double -> ColWidth
fromWidth [Double]
widths')
where
fromWidth :: Double -> ColWidth
fromWidth Double
n
| Double
n forall a. Ord a => a -> a -> Bool
> Double
0 = Double -> ColWidth
ColWidth Double
n
| Bool
otherwise = ColWidth
ColWidthDefault
totalWidth :: Double
totalWidth = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Double]
widths
widths' :: [Double]
widths' = if Double
totalWidth forall a. Ord a => a -> a -> Bool
< Double
1
then [Double]
widths
else forall a b. (a -> b) -> [a] -> [b]
map (forall a. Fractional a => a -> a -> a
/ Double
totalWidth) [Double]
widths
data TableNormalization
= NoNormalization
|
gridTableWith :: (Monad m, Monad mf, HasLastStrPosition st, HasReaderOptions st)
=> ParsecT Sources st m (mf Blocks)
-> ParsecT Sources st m (mf Blocks)
gridTableWith :: forall (m :: * -> *) (mf :: * -> *) st.
(Monad m, Monad mf, HasLastStrPosition st, HasReaderOptions st) =>
ParsecT Sources st m (mf Blocks)
-> ParsecT Sources st m (mf Blocks)
gridTableWith ParsecT Sources st m (mf Blocks)
blocks = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap TableComponents -> Blocks
tableFromComponents forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
forall (m :: * -> *) (mf :: * -> *) st.
(Monad m, Monad mf, HasReaderOptions st, HasLastStrPosition st) =>
TableNormalization
-> ParsecT Sources st m (mf Blocks)
-> ParsecT Sources st m (mf TableComponents)
gridTableWith' TableNormalization
NoNormalization ParsecT Sources st m (mf Blocks)
blocks
gridTableWith' :: (Monad m, Monad mf,
HasReaderOptions st, HasLastStrPosition st)
=> TableNormalization
-> ParsecT Sources st m (mf Blocks)
-> ParsecT Sources st m (mf TableComponents)
gridTableWith' :: forall (m :: * -> *) (mf :: * -> *) st.
(Monad m, Monad mf, HasReaderOptions st, HasLastStrPosition st) =>
TableNormalization
-> ParsecT Sources st m (mf Blocks)
-> ParsecT Sources st m (mf TableComponents)
gridTableWith' TableNormalization
normalization ParsecT Sources st m (mf Blocks)
blocks = do
ArrayTable [Text]
tbl <- forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m (ArrayTable [Text])
GT.gridTable forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m ()
optional forall s (m :: * -> *) st.
(Stream s m Char, UpdateSourcePos s Char) =>
ParsecT s st m Text
blanklines
let blkTbl :: ArrayTable (ParsecT Sources st m (mf Blocks))
blkTbl = forall a b. (a -> b) -> ArrayTable a -> ArrayTable b
GT.mapCells
(\[Text]
lns -> forall (m :: * -> *) u a.
(Monad m, HasLastStrPosition u) =>
ParsecT Sources u m a -> Text -> ParsecT Sources u m a
parseFromString' ParsecT Sources st m (mf Blocks)
blocks
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip Text -> Char -> Text
T.snoc Char
'\n'
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
T.unlines
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> [Text]
removeOneLeadingSpace
forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
T.stripEnd [Text]
lns)
ArrayTable [Text]
tbl
let rows :: [[Cell (ParsecT Sources st m (mf Blocks))]]
rows = forall a. ArrayTable a -> [[Cell a]]
GT.rows ArrayTable (ParsecT Sources st m (mf Blocks))
blkTbl
let toPandocCell :: Cell (f (f Blocks)) -> f (f Cell)
toPandocCell (GT.Cell f (f Blocks)
c (GT.RowSpan Int
rs) (GT.ColSpan Int
cs)) =
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Alignment -> RowSpan -> ColSpan -> Blocks -> Cell
B.cell Alignment
AlignDefault (Int -> RowSpan
B.RowSpan Int
rs) (Int -> ColSpan
B.ColSpan Int
cs) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Blocks -> Blocks
plainify) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f (f Blocks)
c
[[mf Cell]]
rows' <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall {f :: * -> *} {f :: * -> *}.
(Functor f, Functor f) =>
Cell (f (f Blocks)) -> f (f Cell)
toPandocCell) [[Cell (ParsecT Sources st m (mf Blocks))]]
rows
Int
columns <- forall st s (m :: * -> *) t b.
(HasReaderOptions st, Stream s m t) =>
(ReaderOptions -> b) -> ParsecT s st m b
getOption ReaderOptions -> Int
readerColumns
let colspecs :: [ColSpec]
colspecs = forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\(Alignment, Int)
cs Double
w -> (Alignment -> Alignment
convAlign forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> a
fst (Alignment, Int)
cs, Double -> ColWidth
B.ColWidth Double
w))
(forall i e. Array i e -> [e]
elems forall a b. (a -> b) -> a -> b
$ forall a. ArrayTable a -> Array ColIndex (Alignment, Int)
GT.arrayTableColSpecs ArrayTable [Text]
tbl)
(forall a. ArrayTable a -> Int -> [Double]
fractionalColumnWidths ArrayTable [Text]
tbl Int
columns)
let caption :: Caption
caption = Caption
B.emptyCaption
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ do
[[Cell]]
rows'' <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [[mf Cell]]
rows'
let headLen :: Int
headLen = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 RowIndex -> Int
GT.fromRowIndex forall a b. (a -> b) -> a -> b
$ forall a. ArrayTable a -> Maybe RowIndex
GT.arrayTableHead ArrayTable [Text]
tbl
let ([Row]
hRows, [Row]
bRows') =
forall a. Int -> [a] -> ([a], [a])
splitAt Int
headLen (forall a b. (a -> b) -> [a] -> [b]
map (Attr -> [Cell] -> Row
B.Row Attr
B.nullAttr) [[Cell]]
rows'')
let ([Row]
bRows, [Row]
fRows) =
case forall a. ArrayTable a -> Maybe RowIndex
GT.arrayTableFoot ArrayTable [Text]
tbl of
Just RowIndex
fIdx -> forall a. Int -> [a] -> ([a], [a])
splitAt (RowIndex -> Int
GT.fromRowIndex RowIndex
fIdx forall a. Num a => a -> a -> a
- Int
headLen forall a. Num a => a -> a -> a
- Int
1) [Row]
bRows'
Maybe RowIndex
Nothing -> ([Row]
bRows', [])
let thead :: TableHead
thead = Attr -> [Row] -> TableHead
B.TableHead Attr
B.nullAttr forall a b. (a -> b) -> a -> b
$ case ([Row]
hRows, TableNormalization
normalization) of
([Row
hrow], TableNormalization
NormalizeHeader) ->
let Row Attr
_attr [Cell]
cells = Row
hrow
simple :: Cell -> Bool
simple = \case
Cell (Text
"",[],[]) Alignment
AlignDefault (RowSpan Int
1) (ColSpan Int
1) [] ->
Bool
True
Cell
_ ->
Bool
False
in [Attr -> [Cell] -> Row
B.Row Attr
nullAttr [Cell]
cells | Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Cell]
cells) Bool -> Bool -> Bool
&&
Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Cell -> Bool
simple [Cell]
cells)]
([Row], TableNormalization)
_ -> [Row]
hRows
let tfoot :: TableFoot
tfoot = Attr -> [Row] -> TableFoot
B.TableFoot Attr
B.nullAttr [Row]
fRows
let tbody :: TableBody
tbody = Attr -> RowHeadColumns -> [Row] -> [Row] -> TableBody
B.TableBody Attr
B.nullAttr RowHeadColumns
0 [] [Row]
bRows
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Attr
-> Caption
-> [ColSpec]
-> TableHead
-> [TableBody]
-> TableFoot
-> TableComponents
TableComponents Attr
nullAttr Caption
caption [ColSpec]
colspecs TableHead
thead [TableBody
tbody] TableFoot
tfoot
removeOneLeadingSpace :: [Text] -> [Text]
removeOneLeadingSpace :: [Text] -> [Text]
removeOneLeadingSpace [Text]
xs =
if forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Text -> Bool
startsWithSpace [Text]
xs
then forall a b. (a -> b) -> [a] -> [b]
map (Int -> Text -> Text
T.drop Int
1) [Text]
xs
else [Text]
xs
where startsWithSpace :: Text -> Bool
startsWithSpace Text
t = case Text -> Maybe (Char, Text)
T.uncons Text
t of
Maybe (Char, Text)
Nothing -> Bool
True
Just (Char
c, Text
_) -> Char
c forall a. Eq a => a -> a -> Bool
== Char
' '
plainify :: B.Blocks -> B.Blocks
plainify :: Blocks -> Blocks
plainify Blocks
blks = case forall a. Many a -> [a]
B.toList Blocks
blks of
[Para [Inline]
x] -> forall a. [a] -> Many a
B.fromList [[Inline] -> Block
Plain [Inline]
x]
[Block]
_ -> Blocks
blks
convAlign :: GT.Alignment -> B.Alignment
convAlign :: Alignment -> Alignment
convAlign Alignment
GT.AlignLeft = Alignment
B.AlignLeft
convAlign Alignment
GT.AlignRight = Alignment
B.AlignRight
convAlign Alignment
GT.AlignCenter = Alignment
B.AlignCenter
convAlign Alignment
GT.AlignDefault = Alignment
B.AlignDefault
fractionalColumnWidths :: GT.ArrayTable a -> Int -> [Double]
fractionalColumnWidths :: forall a. ArrayTable a -> Int -> [Double]
fractionalColumnWidths ArrayTable a
gt Int
charColumns =
let widths :: [Int]
widths = forall a b. (a -> b) -> [a] -> [b]
map ((forall a. Num a => a -> a -> a
+Int
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd)
(forall i e. Array i e -> [e]
elems forall a b. (a -> b) -> a -> b
$ forall a. ArrayTable a -> Array ColIndex (Alignment, Int)
GT.arrayTableColSpecs ArrayTable a
gt)
norm :: Double
norm = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Ord a => a -> a -> a
max (forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
widths forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
widths forall a. Num a => a -> a -> a
- Int
2) Int
charColumns
in forall a b. (a -> b) -> [a] -> [b]
map (\Int
w -> forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
w forall a. Fractional a => a -> a -> a
/ Double
norm) [Int]
widths
tableWith :: (Stream s m Char, UpdateSourcePos s Char,
HasReaderOptions st, Monad mf)
=> ParsecT s st m (mf [Blocks], [Alignment], [Int])
-> ([Int] -> ParsecT s st m (mf [Blocks]))
-> ParsecT s st m sep
-> ParsecT s st m end
-> ParsecT s st m (mf Blocks)
tableWith :: forall s (m :: * -> *) st (mf :: * -> *) sep end.
(Stream s m Char, UpdateSourcePos s Char, HasReaderOptions st,
Monad mf) =>
ParsecT s st m (mf [Blocks], [Alignment], [Int])
-> ([Int] -> ParsecT s st m (mf [Blocks]))
-> ParsecT s st m sep
-> ParsecT s st m end
-> ParsecT s st m (mf Blocks)
tableWith ParsecT s st m (mf [Blocks], [Alignment], [Int])
hp [Int] -> ParsecT s st m (mf [Blocks])
rp ParsecT s st m sep
lp ParsecT s st m end
fp = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap TableComponents -> Blocks
tableFromComponents forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
forall s (m :: * -> *) st (mf :: * -> *) sep end.
(Stream s m Char, UpdateSourcePos s Char, HasReaderOptions st,
Monad mf) =>
TableNormalization
-> ParsecT s st m (mf [Blocks], [Alignment], [Int])
-> ([Int] -> ParsecT s st m (mf [Blocks]))
-> ParsecT s st m sep
-> ParsecT s st m end
-> ParsecT s st m (mf TableComponents)
tableWith' TableNormalization
NoNormalization ParsecT s st m (mf [Blocks], [Alignment], [Int])
hp [Int] -> ParsecT s st m (mf [Blocks])
rp ParsecT s st m sep
lp ParsecT s st m end
fp
tableWith' :: (Stream s m Char, UpdateSourcePos s Char,
HasReaderOptions st, Monad mf)
=> TableNormalization
-> ParsecT s st m (mf [Blocks], [Alignment], [Int])
-> ([Int] -> ParsecT s st m (mf [Blocks]))
-> ParsecT s st m sep
-> ParsecT s st m end
-> ParsecT s st m (mf TableComponents)
tableWith' :: forall s (m :: * -> *) st (mf :: * -> *) sep end.
(Stream s m Char, UpdateSourcePos s Char, HasReaderOptions st,
Monad mf) =>
TableNormalization
-> ParsecT s st m (mf [Blocks], [Alignment], [Int])
-> ([Int] -> ParsecT s st m (mf [Blocks]))
-> ParsecT s st m sep
-> ParsecT s st m end
-> ParsecT s st m (mf TableComponents)
tableWith' TableNormalization
n11n ParsecT s st m (mf [Blocks], [Alignment], [Int])
headerParser [Int] -> ParsecT s st m (mf [Blocks])
rowParser ParsecT s st m sep
lineParser ParsecT s st m end
footerParser = forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try forall a b. (a -> b) -> a -> b
$ do
(mf [Blocks]
heads, [Alignment]
aligns, [Int]
indices) <- ParsecT s st m (mf [Blocks], [Alignment], [Int])
headerParser
mf [[Blocks]]
lines' <- forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int] -> ParsecT s st m (mf [Blocks])
rowParser [Int]
indices forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
`sepEndBy1` ParsecT s st m sep
lineParser
ParsecT s st m end
footerParser
Int
numColumns <- forall st s (m :: * -> *) t b.
(HasReaderOptions st, Stream s m t) =>
(ReaderOptions -> b) -> ParsecT s st m b
getOption ReaderOptions -> Int
readerColumns
let widths :: [Double]
widths = if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Int]
indices
then forall a. Int -> a -> [a]
replicate (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Alignment]
aligns) Double
0.0
else Int -> [Int] -> [Double]
widthsFromIndices Int
numColumns [Int]
indices
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ TableNormalization
-> [Alignment]
-> [Double]
-> [Blocks]
-> [[Blocks]]
-> TableComponents
toTableComponents' TableNormalization
n11n [Alignment]
aligns [Double]
widths forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> mf [Blocks]
heads forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> mf [[Blocks]]
lines'
toRow :: [Blocks] -> Row
toRow :: [Blocks] -> Row
toRow = Attr -> [Cell] -> Row
Row Attr
nullAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map Blocks -> Cell
B.simpleCell
toHeaderRow :: TableNormalization -> [Blocks] -> [Row]
= \case
TableNormalization
NoNormalization -> \[Blocks]
l -> [[Blocks] -> Row
toRow [Blocks]
l | Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Blocks]
l)]
TableNormalization
NormalizeHeader -> \[Blocks]
l -> [[Blocks] -> Row
toRow [Blocks]
l | Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Blocks]
l) Bool -> Bool -> Bool
&& Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Blocks]
l)]
widthsFromIndices :: Int
-> [Int]
-> [Double]
widthsFromIndices :: Int -> [Int] -> [Double]
widthsFromIndices Int
_ [] = []
widthsFromIndices Int
numColumns' [Int]
indices =
let numColumns :: Int
numColumns = forall a. Ord a => a -> a -> a
max Int
numColumns' (forall a. a -> [a] -> a
lastDef Int
0 [Int]
indices)
lengths' :: [Int]
lengths' = forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (-) [Int]
indices (Int
0forall a. a -> [a] -> [a]
:[Int]
indices)
lengths :: [Int]
lengths = forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$
case forall a. [a] -> [a]
reverse [Int]
lengths' of
[] -> []
[Int
x] -> [Int
x]
(Int
x:Int
y:[Int]
zs) -> if Int
x forall a. Ord a => a -> a -> Bool
< Int
y Bool -> Bool -> Bool
&& Int
y forall a. Num a => a -> a -> a
- Int
x forall a. Ord a => a -> a -> Bool
<= Int
2
then Int
yforall a. a -> [a] -> [a]
:Int
yforall a. a -> [a] -> [a]
:[Int]
zs
else Int
xforall a. a -> [a] -> [a]
:Int
yforall a. a -> [a] -> [a]
:[Int]
zs
totLength :: Int
totLength = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
lengths
quotient :: Double
quotient = if Int
totLength forall a. Ord a => a -> a -> Bool
> Int
numColumns
then forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
totLength
else forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
numColumns
fracs :: [Double]
fracs = forall a b. (a -> b) -> [a] -> [b]
map (\Int
l -> forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l forall a. Fractional a => a -> a -> a
/ Double
quotient) [Int]
lengths in
forall a. [a] -> [a]
tail [Double]
fracs