aboutsummaryrefslogtreecommitdiffstats
path: root/RealCalc.hs
blob: bf7b3d589d81d30963cc516369f8b033c0041d82 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
{-# LANGUAGE RankNTypes #-}

module RealCalc (calculate) where

import qualified Expr

data Result = RInt Integer | RFloat Double

instance Show Result where
  show (RInt i) = show i
  show (RFloat d) = show d

rToDouble :: Result -> Double
rToDouble (RInt i) = fromIntegral i
rToDouble (RFloat d) = d

genericCombine :: (forall a. Num a => a -> a -> a) -> Result
               -> Result -> Result
genericCombine f i j =
  case (i, j) of
    (RInt a, RInt b) -> RInt (f a b)
    _ -> RFloat (f (rToDouble i) (rToDouble j))

genericInner :: (forall a. Num a => a -> a) -> Result -> Result
genericInner f (RInt i) = RInt (f i)
genericInner f (RFloat d) = RFloat (f d)

simplify :: Expr.Expr -> Result
simplify (Expr.Plus e1 e2) =
  genericCombine (+) (simplify e1) (simplify e2)
simplify (Expr.Negate e) = genericInner negate (simplify e)
simplify (Expr.Minus e1 e2) =
  genericCombine (-) (simplify e1) (simplify e2)
simplify (Expr.Times e1 e2) =
  genericCombine (*) (simplify e1) (simplify e2)
simplify (Expr.Div e1 e2) =
  RFloat (rToDouble (simplify e1) / rToDouble (simplify e2))
simplify (Expr.EInt i) = RInt i
simplify (Expr.EFloat d) = RFloat d
simplify Expr.E = RFloat (exp 1)
simplify Expr.Pi = RFloat pi
simplify (Expr.Log e) = RFloat . log . rToDouble $ simplify e
simplify (Expr.Sin e) = RFloat . sin . rToDouble $ simplify e
simplify (Expr.Cos e) = RFloat . cos . rToDouble $ simplify e
simplify (Expr.Sqrt e) = RFloat . sqrt . rToDouble $ simplify e

calculate :: String -> Maybe String
calculate s = case Expr.parseE s of
                Left _ -> Nothing
                Right e -> Just . show $ simplify e