aboutsummaryrefslogtreecommitdiffstats
path: root/RealCalc.hs
blob: 11eebe41ec57e6aa32630b3cb02a0a57f6d0ee81 (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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
{-# LANGUAGE RankNTypes #-}

{-
 - Copyright 2018 Raymond Hogenson
 -
 - This file is part of RealCalc.

 - RealCalc is free software: you can redistribute it and/or modify
 - it under the terms of the GNU General Public License as published by
 - the Free Software Foundation, either version 3 of the License, or
 - (at your option) any later version.
 - 
 - RealCalc is distributed in the hope that it will be useful,
 - but WITHOUT ANY WARRANTY; without even the implied warranty of
 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 - GNU General Public License for more details.
 - 
 - You should have received a copy of the GNU General Public License
 - along with RealCalc.  If not, see <http://www.gnu.org/licenses/>.
 -}

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