diff --git a/src/Math/Haskellator.hs b/src/Math/Haskellator.hs index e8418ed..6a9285f 100644 --- a/src/Math/Haskellator.hs +++ b/src/Math/Haskellator.hs @@ -1,6 +1,6 @@ -- | Calculator module for evaluating mathematical expressions containing SI units -module Math.Haskellator (EvalValue, calculate) where +module Math.Haskellator (calculate) where import Control.Monad @@ -9,12 +9,8 @@ import Math.Haskellator.Internal.AstProcessingSteps.Normalize import Math.Haskellator.Internal.Expr import Math.Haskellator.Internal.Lexer import Math.Haskellator.Internal.Parser -import Math.Haskellator.Internal.Units import Math.Haskellator.Internal.Utils.Error --- | The specific 'Value' type returned by the evaluation -type EvalValue = Value Dimension - getAst :: String -> Either Error Expr getAst = scan >=> parse >=> normalize diff --git a/src/Math/Haskellator/Internal/AstProcessingSteps/Evaluate.hs b/src/Math/Haskellator/Internal/AstProcessingSteps/Evaluate.hs index 1e85e0e..4c130bb 100644 --- a/src/Math/Haskellator/Internal/AstProcessingSteps/Evaluate.hs +++ b/src/Math/Haskellator/Internal/AstProcessingSteps/Evaluate.hs @@ -3,7 +3,8 @@ -- | Evaluate the expression tree to a numeric value and a dimension. module Math.Haskellator.Internal.AstProcessingSteps.Evaluate ( - evaluate + EvalValue + , evaluate , execute , mergeUnits , subtractUnits @@ -18,6 +19,9 @@ import Math.Haskellator.Internal.Operators import Math.Haskellator.Internal.Units import Math.Haskellator.Internal.Utils.Error +-- | The specific 'Value' type returned by the evaluation +type EvalValue = Value Dimension + -- | Evaluate an expression tree to a numeric value evaluate :: Expr -- ^ the expression tree to evaluate -> Either Error Double -- ^ the numeric result or an error @@ -25,18 +29,18 @@ evaluate expr = execute expr <&> value -- | Determine the result (value and dimension) of an expression tree execute :: Expr -- ^ the expression tree to evaluate - -> Either Error (Value Dimension) -- ^ the result or an error + -> Either Error EvalValue -- ^ the result or an error execute expr = do r <- runAstFold $ execute' expr return $ r { unit = filterZeroPower $ unit r } -execute' :: Expr -> SimpleAstFold (Value Dimension) +execute' :: Expr -> SimpleAstFold EvalValue execute' = partiallyFoldExprM execVal execBinOp execUnaryOp execConversion execVarBinds execVar -execVal :: Value Dimension -> SimpleAstFold (Value Dimension) +execVal :: EvalValue -> SimpleAstFold EvalValue execVal = return -execBinOp :: Value Dimension -> Op -> Value Dimension -> SimpleAstFold (Value Dimension) +execBinOp :: EvalValue -> Op -> EvalValue -> SimpleAstFold EvalValue execBinOp lhs Plus rhs | unit lhs == unit rhs = return $ combineValues (+) lhs rhs | otherwise = throwError $ Error RuntimeError $ "Cannot add units " ++ show (unit lhs) ++ " and " ++ show (unit rhs) execBinOp lhs Minus rhs | unit lhs == unit rhs = return $ combineValues (-) lhs rhs @@ -54,20 +58,20 @@ execBinOp lhs Pow rhs = case rhs of _ -> throwError $ Error RuntimeError "Exponentiation of units is not supported" execBinOp _ op _ = throwError $ Error ImplementationError $ "Unknown binary operator " ++ show op -execUnaryOp :: Op -> Value Dimension -> SimpleAstFold (Value Dimension) +execUnaryOp :: Op -> EvalValue -> SimpleAstFold EvalValue execUnaryOp op rhs = case op of UnaryMinus -> return $ mapValue (0-) rhs _ -> throwError $ Error ImplementationError $ "Unknown unary operator " ++ show op -execConversion :: Value Dimension -> Dimension -> SimpleAstFold (Value Dimension) +execConversion :: EvalValue -> Dimension -> SimpleAstFold EvalValue execConversion _ _ = throwError $ Error ImplementationError "Conversion is handled elsewhere" -execVarBinds :: Bindings Expr -> Expr -> SimpleAstFold (Value Dimension) +execVarBinds :: Bindings Expr -> Expr -> SimpleAstFold EvalValue execVarBinds bs expr = runInNewScope $ do bindVars $ fmap Expr <$> bs execute' expr -execVar :: String -> SimpleAstFold (Value Dimension) +execVar :: String -> SimpleAstFold EvalValue execVar n = getVarBinding n >>= \case (Result v) -> return v (Expr e) -> do