module Domain.Math.SquareRoot.Views
( squareRootView, squareRootViewWith
) where
import Control.Monad
import Domain.Math.Data.SquareRoot
import Domain.Math.Expr hiding ((^))
import Domain.Math.Numeric.Views
import Domain.Math.Safe
import Ideas.Common.View
squareRootView :: View Expr (SquareRoot Expr)
squareRootView = squareRootViewWith identity
squareRootViewWith :: (Eq a,Fractional a) => View Expr a -> View Expr (SquareRoot a)
squareRootViewWith v = makeView f g
where
f expr =
case expr of
Nat a -> Just (fromIntegral a)
a :+: b -> (+) <$> f a <*> f b
a :-: b -> (-) <$> f a <*> f b
Negate a -> fmap negate (f a)
a :*: b -> (*) <$> f a <*> f b
a :/: b -> join $ safeDiv <$> f a <*> f b
Sqrt a -> fmap sqrtRational (match rationalView a)
Sym s [a, b] | isPowerSymbol s ->
power <$> f a <*> match integerView b
_ -> fmap con (match v expr)
power a n
| n >= 0 = a ^ n
| otherwise = 1 / (a ^ abs n)
g = to sumView . map h . toList
h (a, n)
| n == 0 = 0
| n == 1 = build v a
| otherwise = build v a .*. Sqrt (fromIntegral n)