classify-frog-0.2.3: src/Spreadsheet/Row.hs
module Spreadsheet.Row (
M,
exec,
run,
Value,
Fraction,
Precision(..),
putEmpty,
putValueFormula,
putValue,
putFractionFormula,
putFraction,
putPlainFraction,
putString,
putAnchor,
putInt,
putNumber,
FieldTracked,
FieldType(..),
TableField(..),
emptyField,
fractionField,
fracFieldFromTracked,
) where
import qualified Spreadsheet.Formula as CalcForm
import Spreadsheet.Formula
(FormulaTracked, CellTracked, Tracked(Tracked), untracked)
import qualified Control.Monad.Trans.RWS as MRWS
import Control.Monad (liftM2)
import Data.Bifunctor (bimap, )
import Text.Printf (PrintfArg, printf)
import qualified Algebra.Field as Field
import qualified Algebra.Ring as Ring
import NumericPrelude.Numeric
import NumericPrelude.Base
import Prelude ()
data FieldType = TypeString | TypeNumber
deriving (Eq, Ord, Enum, Show)
type FieldTracked = TableField (Tracked (Maybe CalcForm.Formula) String)
data TableField a =
TableField {
fieldType :: FieldType,
fieldQuoted :: Bool,
fieldAnchor :: String,
fieldHead :: Bool,
fieldSpan :: Int,
fieldPrecision :: Maybe Precision,
fieldContent :: a
}
instance Functor TableField where
fmap f x = x{fieldContent = f $ fieldContent x}
type M = MRWS.RWS Int [FieldTracked] Int
exec :: Int -> M () -> [FieldTracked]
exec row act = snd $ run row act
run :: Int -> M row -> (row, [FieldTracked])
run row act = MRWS.evalRWS act row 0
makeField :: Bool -> a -> TableField a
makeField quote content =
TableField {
fieldType = TypeString,
fieldQuoted = quote,
fieldAnchor = "",
fieldHead = False,
fieldSpan = 1,
fieldPrecision = Nothing,
fieldContent = content
}
putString :: String -> M ()
putString str =
put $ makeField True $ untracked str
putAnchor :: String -> String -> M ()
putAnchor ref str =
put $ (makeField True $ untracked str) {fieldAnchor = ref}
put :: FieldTracked -> M ()
put x = do
column <- MRWS.get
MRWS.tell [x]
MRWS.put $! column + fieldSpan x
putEmpty :: M ()
putEmpty = put emptyField
putInt :: (Ring.C a) => Int -> M (CellTracked a)
putInt = fmap CalcForm.fromInt . putNumber
getCellName :: M CalcForm.CellId
getCellName = liftM2 CalcForm.CellId MRWS.ask MRWS.get
putNumber :: (Value a) => a -> M (CellTracked a)
putNumber x = do
cell <- getCellName
put $ (makeField False $ untracked $ formatValue x) {fieldType = TypeNumber}
return $ Tracked cell x
putValue :: (Value a) => FormulaTracked a -> M (CellTracked a)
putValue x = do
cell <- getCellName
put $ fieldFromTracked x
return $ x{CalcForm.trackedFormula = cell}
putValueFormula :: (Value a) => FormulaTracked a -> M (FormulaTracked a)
putValueFormula = fmap CalcForm.trackedVar . putValue
putFraction ::
(Fraction a) => Precision -> FormulaTracked a -> M (CellTracked a)
putFraction prec x = do
cell <- getCellName
put $ fracFieldFromTracked prec x
return $ x{CalcForm.trackedFormula = cell}
putPlainFraction :: (Fraction a) => Precision -> a -> M (CellTracked a)
putPlainFraction prec x = do
cell <- getCellName
put $ fractionField prec x
return $ Tracked cell x
putFractionFormula ::
(Fraction a) => Precision -> FormulaTracked a -> M (FormulaTracked a)
putFractionFormula prec = fmap CalcForm.trackedVar . putFraction prec
class Value a where
{- |
Convert a value to a text representation
that is compatible to spreadsheet processors.
-}
formatValue :: a -> String
instance Value Int where
formatValue = show
instance Value Integer where
formatValue = show
instance Value Float where
formatValue = show
instance Value Double where
formatValue = show
data Precision = Prec0 | Prec3 | Prec6
deriving (Eq, Ord, Enum)
class (Value a, Field.C a) => Fraction a where
formatFraction :: Precision -> a -> String
instance Fraction Float where
formatFraction = formatFractionDefault
instance Fraction Double where
formatFraction = formatFractionDefault
formatFractionDefault :: (PrintfArg a) => Precision -> a -> String
formatFractionDefault prec = printf (precisionFormat prec)
precisionFormat :: Precision -> String
precisionFormat prec =
case prec of
Prec0 -> "%.0f"
Prec3 -> "%.3f"
Prec6 -> "%.6f"
fieldFromTracked :: Value a => Tracked CalcForm.Formula a -> FieldTracked
fieldFromTracked x =
(makeField False $ bimap Just formatValue x) {fieldType = TypeNumber}
fracFieldFromTracked ::
Fraction a => Precision -> Tracked CalcForm.Formula a -> FieldTracked
fracFieldFromTracked prec x =
(makeField False $ bimap Just (formatFraction prec) x)
{fieldType = TypeNumber, fieldPrecision = Just prec}
emptyField :: FieldTracked
emptyField = makeField False $ untracked ""
fractionField :: (Fraction a) => Precision -> a -> FieldTracked
fractionField prec a =
(makeField False $ untracked $ formatFraction prec a)
{fieldType = TypeNumber, fieldPrecision = Just prec}