    -- | Symbolic number, i.e., these are not numbers at all, but just build
    -- a representation of the expressions.
    -- This implementation is incomplete in that it allows comnstruction,
    -- but not deconstruction of the expressions.  It's mainly useful for
    -- debugging.
    module Data.Number.Symbolic(Sym, var, con, subst, unSym) where

    import Data.Char(isAlpha)
    import Data.Maybe(fromMaybe)

    -- | Symbolic numbers over some base type for the literals.
    data Sym a = Con a | App String ([a]->a) [Sym a]

    instance (Eq a) => Eq (Sym a) where
        Con a
    x      == :: Sym a -> Sym a -> Bool
    == Con a
    x'        =  a
    x a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    x'
        App String
    f [a] -> a
    _ [Sym a]
    xs == App String
    f' [a] -> a
    _ [Sym a]
    xs'  =  (String
    f, [Sym a]
    xs) (String, [Sym a]) -> (String, [Sym a]) -> Bool
    forall a. Eq a => a -> a -> Bool
    == (String
    f', [Sym a]
    xs')
        Sym a
    _          == Sym a
    _             =  Bool
    False

    instance (Ord a) => Ord (Sym a) where
        Con a
    x      compare :: Sym a -> Sym a -> Ordering
    `compare` Con a
    x'        =  a
    x a -> a -> Ordering
    forall a. Ord a => a -> a -> Ordering
    `compare` a
    x'
        Con a
    _      `compare` App String
    _ [a] -> a
    _ [Sym a]
    _     = Ordering
    LT
        App String
    _ [a] -> a
    _ [Sym a]
    _  `compare` Con a
    _         = Ordering
    GT
        App String
    f [a] -> a
    _ [Sym a]
    xs `compare` App String
    f' [a] -> a
    _ [Sym a]
    xs'  =  (String
    f, [Sym a]
    xs) (String, [Sym a]) -> (String, [Sym a]) -> Ordering
    forall a. Ord a => a -> a -> Ordering
    `compare` (String
    f', [Sym a]
    xs')

    -- | Create a variable.
    var :: String -> Sym a
    var :: forall a. String -> Sym a
    var String
    s = String -> ([a] -> a) -> [Sym a] -> Sym a
    forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
    App String
    s [a] -> a
    forall a. HasCallStack => a
    undefined []

    -- | Create a constant (useful when it is not a literal).
    con :: a -> Sym a
    con :: forall a. a -> Sym a
    con = a -> Sym a
    forall a. a -> Sym a
    Con

    -- | The expression @subst x v e@ substitutes the expression @v@ for each
    -- occurence of the variable @x@ in @e@.
    subst :: (Num a, Eq a) => String -> Sym a -> Sym a -> Sym a
    subst :: forall a. (Num a, Eq a) => String -> Sym a -> Sym a -> Sym a
    subst String
    _ Sym a
    _ e :: Sym a
    e@(Con a
    _) = Sym a
    e
    subst String
    x Sym a
    v e :: Sym a
    e@(App String
    x' [a] -> a
    _ []) | String
    x String -> String -> Bool
    forall a. Eq a => a -> a -> Bool
    == String
    x' = Sym a
    v
                              | Bool
    otherwise = Sym a
    e
    subst String
    x Sym a
    v (App String
    s [a] -> a
    f [Sym a]
    es) =
        case (Sym a -> Sym a) -> [Sym a] -> [Sym a]
    forall a b. (a -> b) -> [a] -> [b]
    map (String -> Sym a -> Sym a -> Sym a
    forall a. (Num a, Eq a) => String -> Sym a -> Sym a -> Sym a
    subst String
    x Sym a
    v) [Sym a]
    es of
        [Sym a
    e] -> (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp (\ a
    x -> [a] -> a
    f [a
    x]) String
    s Sym a
    e
        [Sym a
    e1,Sym a
    e2] -> (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp (\ a
    x a
    y -> [a] -> a
    f [a
    x,a
    y]) Sym a
    e1 String
    s Sym a
    e2
        [Sym a]
    es' -> String -> ([a] -> a) -> [Sym a] -> Sym a
    forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
    App String
    s [a] -> a
    f [Sym a]
    es'

    -- Turn a symbolic number into a regular one if it is a constant,
    -- otherwise generate an error.
    unSym :: (Show a) => Sym a -> a
    unSym :: forall a. Show a => Sym a -> a
    unSym (Con a
    c) = a
    c
    unSym Sym a
    e = String -> a
    forall a. HasCallStack => String -> a
    error (String -> a) -> String -> a
    forall a b. (a -> b) -> a -> b
    $ String
    "unSym called: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Sym a -> String
    forall a. Show a => a -> String
    show Sym a
    e

    instance (Show a) => Show (Sym a) where
        showsPrec :: Int -> Sym a -> String -> String
    showsPrec Int
    p (Con a
    c) = Int -> a -> String -> String
    forall a. Show a => Int -> a -> String -> String
    showsPrec Int
    p a
    c
        showsPrec Int
    _ (App String
    s [a] -> a
    _ []) = String -> String -> String
    showString String
    s
        showsPrec Int
    p (App op :: String
    op@(Char
    c:String
    _) [a] -> a
    _ [Sym a
    x, Sym a
    y]) | Bool -> Bool
    not (Char -> Bool
    isAlpha Char
    c) =
            Bool -> (String -> String) -> String -> String
    showParen (Int
    pInt -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >Int
    q) (Int -> Sym a -> String -> String
    forall a. Show a => Int -> a -> String -> String
    showsPrec Int
    ql Sym a
    x (String -> String) -> (String -> String) -> String -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> String -> String
    showString String
    op (String -> String) -> (String -> String) -> String -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Sym a -> String -> String
    forall a. Show a => Int -> a -> String -> String
    showsPrec Int
    qr Sym a
    y)
            where (Int
    ql, Int
    q, Int
    qr) = (Int, Int, Int) -> Maybe (Int, Int, Int) -> (Int, Int, Int)
    forall a. a -> Maybe a -> a
    fromMaybe (Int
    9,Int
    9,Int
    9) (Maybe (Int, Int, Int) -> (Int, Int, Int))
    -> Maybe (Int, Int, Int) -> (Int, Int, Int)
    forall a b. (a -> b) -> a -> b
    $ String -> [(String, (Int, Int, Int))] -> Maybe (Int, Int, Int)
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup String
    op [
                       (String
    "**", (Int
    9,Int
    8,Int
    8)),
                       (String
    "/",  (Int
    7,Int
    7,Int
    8)),
                       (String
    "*",  (Int
    7,Int
    7,Int
    8)),
                       (String
    "+",  (Int
    6,Int
    6,Int
    7)),
                       (String
    "-",  (Int
    6,Int
    6,Int
    7))]
        showsPrec Int
    p (App String
    "negate" [a] -> a
    _ [Sym a
    x]) =
            Bool -> (String -> String) -> String -> String
    showParen (Int
    pInt -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >=Int
    6) (String -> String -> String
    showString String
    "-" (String -> String) -> (String -> String) -> String -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Sym a -> String -> String
    forall a. Show a => Int -> a -> String -> String
    showsPrec Int
    7 Sym a
    x)
        showsPrec Int
    p (App String
    f [a] -> a
    _ [Sym a]
    xs) =
            Bool -> (String -> String) -> String -> String
    showParen (Int
    pInt -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >Int
    10) (((String -> String) -> (String -> String) -> String -> String)
    -> (String -> String) -> [String -> String] -> String -> String
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl (String -> String) -> (String -> String) -> String -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    (.) (String -> String -> String
    showString String
    f) ((Sym a -> String -> String) -> [Sym a] -> [String -> String]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ Sym a
    x -> Char -> String -> String
    showChar Char
    ' ' (String -> String) -> (String -> String) -> String -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Sym a -> String -> String
    forall a. Show a => Int -> a -> String -> String
    showsPrec Int
    11 Sym a
    x) [Sym a]
    xs))

    instance (Num a, Eq a) => Num (Sym a) where
        Sym a
    x + :: Sym a -> Sym a -> Sym a
    + Sym a
    y         = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    forall a. Num a => a -> a -> a
    (+) Sym a
    x String
    "+" Sym a
    y
        Sym a
    x - :: Sym a -> Sym a -> Sym a
    - Sym a
    y         = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp (-) Sym a
    x String
    "-" Sym a
    y
        Sym a
    x * :: Sym a -> Sym a -> Sym a
    * Sym a
    y         = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    forall a. Num a => a -> a -> a
    (*) Sym a
    x String
    "*" Sym a
    y
        negate :: Sym a -> Sym a
    negate Sym a
    x      = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Num a => a -> a
    negate String
    "negate" Sym a
    x
        abs :: Sym a -> Sym a
    abs    Sym a
    x      = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Num a => a -> a
    abs    String
    "abs"    Sym a
    x
        signum :: Sym a -> Sym a
    signum Sym a
    x      = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Num a => a -> a
    signum String
    "signum" Sym a
    x
        fromInteger :: Integer -> Sym a
    fromInteger Integer
    x = a -> Sym a
    forall a. a -> Sym a
    Con (Integer -> a
    forall a. Num a => Integer -> a
    fromInteger Integer
    x)

    instance (Fractional a, Eq a) => Fractional (Sym a) where
        Sym a
    x / :: Sym a -> Sym a -> Sym a
    / Sym a
    y          = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    forall a. Fractional a => a -> a -> a
    (/) Sym a
    x String
    "/" Sym a
    y
        fromRational :: Rational -> Sym a
    fromRational Rational
    x = a -> Sym a
    forall a. a -> Sym a
    Con (Rational -> a
    forall a. Fractional a => Rational -> a
    fromRational Rational
    x)

    -- Assume the numbers are a field and simplify a little
    binOp :: (Num a, Eq a) => (a->a->a) -> Sym a -> String -> Sym a -> Sym a
    binOp :: forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    f (Con a
    x) String
    _ (Con a
    y) = a -> Sym a
    forall a. a -> Sym a
    Con (a -> a -> a
    f a
    x a
    y)
    binOp a -> a -> a
    _ Sym a
    x String
    "+" Sym a
    0 = Sym a
    x
    binOp a -> a -> a
    _ Sym a
    0 String
    "+" Sym a
    x = Sym a
    x
    binOp a -> a -> a
    _ Sym a
    x String
    "+" (App String
    "+" [a] -> a
    _ [Sym a
    y, Sym a
    z]) = (Sym a
    x Sym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    + Sym a
    y) Sym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    + Sym a
    z
    binOp a -> a -> a
    _ Sym a
    x String
    "+" Sym a
    y | Sym a -> Bool
    forall a. Sym a -> Bool
    isCon Sym a
    y Bool -> Bool -> Bool
    && Bool -> Bool
    not (Sym a -> Bool
    forall a. Sym a -> Bool
    isCon Sym a
    x) = Sym a
    y Sym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    + Sym a
    x
    binOp a -> a -> a
    _ Sym a
    x String
    "+" (App String
    "negate" [a] -> a
    _ [Sym a
    y]) = Sym a
    x Sym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    - Sym a
    y
    binOp a -> a -> a
    _ Sym a
    x String
    "-" Sym a
    0 = Sym a
    x
    binOp a -> a -> a
    _ Sym a
    x String
    "-" Sym a
    x' | Sym a
    x Sym a -> Sym a -> Bool
    forall a. Eq a => a -> a -> Bool
    == Sym a
    x' = Sym a
    0
    binOp a -> a -> a
    _ Sym a
    x String
    "-" (Con a
    y) | Bool -> Bool
    not (Sym a -> Bool
    forall a. Sym a -> Bool
    isCon Sym a
    x) = a -> Sym a
    forall a. a -> Sym a
    Con (-a
    y) Sym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    + Sym a
    x
    binOp a -> a -> a
    _ Sym a
    _ String
    "*" Sym a
    0 = Sym a
    0
    binOp a -> a -> a
    _ Sym a
    x String
    "*" Sym a
    1 = Sym a
    x
    binOp a -> a -> a
    _ Sym a
    x String
    "*" (-1) = -Sym a
    x
    binOp a -> a -> a
    _ Sym a
    0 String
    "*" Sym a
    _ = Sym a
    0
    binOp a -> a -> a
    _ Sym a
    1 String
    "*" Sym a
    x = Sym a
    x
    binOp a -> a -> a
    _ (-1) String
    "*" Sym a
    x = -Sym a
    x
    binOp a -> a -> a
    _ Sym a
    x String
    "*" (App String
    "*" [a] -> a
    _ [Sym a
    y, Sym a
    z]) = (Sym a
    x Sym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    * Sym a
    y) Sym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    * Sym a
    z
    binOp a -> a -> a
    _ Sym a
    x String
    "*" Sym a
    y | Sym a -> Bool
    forall a. Sym a -> Bool
    isCon Sym a
    y Bool -> Bool -> Bool
    && Bool -> Bool
    not (Sym a -> Bool
    forall a. Sym a -> Bool
    isCon Sym a
    x) = Sym a
    y Sym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    * Sym a
    x
    binOp a -> a -> a
    _ Sym a
    x String
    "*" (App String
    "/" [a] -> a
    f [Sym a
    y, Sym a
    z]) = String -> ([a] -> a) -> [Sym a] -> Sym a
    forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
    App String
    "/" [a] -> a
    f [Sym a
    xSym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    *Sym a
    y, Sym a
    z]
    {-
    binOp _ x "*" (App "+" _ [y, z]) = x*y + x*z
    binOp _ (App "+" _ [y, z]) "*" x = y*x + z*x
    -}
    binOp a -> a -> a
    _ Sym a
    x String
    "/" Sym a
    1 = Sym a
    x
    binOp a -> a -> a
    _ Sym a
    x String
    "/" (-1) = -Sym a
    x
    binOp a -> a -> a
    _ Sym a
    x String
    "/" Sym a
    x' | Sym a
    x Sym a -> Sym a -> Bool
    forall a. Eq a => a -> a -> Bool
    == Sym a
    x' = Sym a
    1
    binOp a -> a -> a
    _ Sym a
    x String
    "/" (App String
    "/" [a] -> a
    f [Sym a
    y, Sym a
    z]) = String -> ([a] -> a) -> [Sym a] -> Sym a
    forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
    App String
    "/" [a] -> a
    f [Sym a
    xSym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    *Sym a
    z, Sym a
    y]
    binOp a -> a -> a
    f (App String
    "**" [a] -> a
    _ [Sym a
    x, Sym a
    y]) String
    "**" Sym a
    z = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    f Sym a
    x String
    "**" (Sym a
    y Sym a -> Sym a -> Sym a
    forall a. Num a => a -> a -> a
    * Sym a
    z)
    binOp a -> a -> a
    _ Sym a
    _ String
    "**" Sym a
    0 = Sym a
    1
    binOp a -> a -> a
    _ Sym a
    0 String
    "**" Sym a
    _ = Sym a
    0
    binOp a -> a -> a
    f Sym a
    x String
    op Sym a
    y = String -> ([a] -> a) -> [Sym a] -> Sym a
    forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
    App String
    op (\ [a
    a,a
    b] -> a -> a -> a
    f a
    a a
    b) [Sym a
    x, Sym a
    y]

    unOp :: (Num a) => (a->a) -> String -> Sym a -> Sym a
    unOp :: forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    f String
    _ (Con a
    c) = a -> Sym a
    forall a. a -> Sym a
    Con (a -> a
    f a
    c)
    unOp a -> a
    _ String
    "negate" (App String
    "negate" [a] -> a
    _ [Sym a
    x]) = Sym a
    x
    unOp a -> a
    _ String
    "abs" e :: Sym a
    e@(App String
    "abs" [a] -> a
    _ [Sym a]
    _) = Sym a
    e
    unOp a -> a
    _ String
    "signum" e :: Sym a
    e@(App String
    "signum" [a] -> a
    _ [Sym a]
    _) = Sym a
    e
    unOp a -> a
    f String
    op Sym a
    x = String -> ([a] -> a) -> [Sym a] -> Sym a
    forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
    App String
    op (\ [a
    a] -> a -> a
    f a
    a) [Sym a
    x]

    isCon :: Sym a -> Bool
    isCon :: forall a. Sym a -> Bool
    isCon (Con a
    _) = Bool
    True
    isCon Sym a
    _ = Bool
    False

    instance (Integral a) => Integral (Sym a) where
        quot :: Sym a -> Sym a -> Sym a
    quot Sym a
    x Sym a
    y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    forall a. Integral a => a -> a -> a
    quot Sym a
    x String
    "quot" Sym a
    y
        rem :: Sym a -> Sym a -> Sym a
    rem Sym a
    x Sym a
    y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    forall a. Integral a => a -> a -> a
    rem Sym a
    x String
    "rem" Sym a
    y
        quotRem :: Sym a -> Sym a -> (Sym a, Sym a)
    quotRem Sym a
    x Sym a
    y = (Sym a -> Sym a -> Sym a
    forall a. Integral a => a -> a -> a
    quot Sym a
    x Sym a
    y, Sym a -> Sym a -> Sym a
    forall a. Integral a => a -> a -> a
    rem Sym a
    x Sym a
    y)
        div :: Sym a -> Sym a -> Sym a
    div Sym a
    x Sym a
    y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    forall a. Integral a => a -> a -> a
    div Sym a
    x String
    "div" Sym a
    y
        mod :: Sym a -> Sym a -> Sym a
    mod Sym a
    x Sym a
    y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    forall a. Integral a => a -> a -> a
    mod Sym a
    x String
    "mod" Sym a
    y
        toInteger :: Sym a -> Integer
    toInteger (Con a
    c) = a -> Integer
    forall a. Integral a => a -> Integer
    toInteger a
    c

    instance (Enum a) => Enum (Sym a) where
        toEnum :: Int -> Sym a
    toEnum = a -> Sym a
    forall a. a -> Sym a
    Con (a -> Sym a) -> (Int -> a) -> Int -> Sym a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> a
    forall a. Enum a => Int -> a
    toEnum
        fromEnum :: Sym a -> Int
    fromEnum (Con a
    a) = a -> Int
    forall a. Enum a => a -> Int
    fromEnum a
    a

    instance (Real a) => Real (Sym a) where
        toRational :: Sym a -> Rational
    toRational (Con a
    c) = a -> Rational
    forall a. Real a => a -> Rational
    toRational a
    c

    instance (RealFrac a) => RealFrac (Sym a) where
        properFraction :: forall b. Integral b => Sym a -> (b, Sym a)
    properFraction (Con a
    c) = (b
    i, a -> Sym a
    forall a. a -> Sym a
    Con a
    c') where (b
    i, a
    c') = a -> (b, a)
    forall b. Integral b => a -> (b, a)
    forall a b. (RealFrac a, Integral b) => a -> (b, a)
    properFraction a
    c

    instance (Floating a, Eq a) => Floating (Sym a) where
        pi :: Sym a
    pi = String -> Sym a
    forall a. String -> Sym a
    var String
    "pi"
        exp :: Sym a -> Sym a
    exp = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    exp String
    "exp"
        sqrt :: Sym a -> Sym a
    sqrt = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    sqrt String
    "sqrt"
        log :: Sym a -> Sym a
    log = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    log String
    "log"
        Sym a
    x ** :: Sym a -> Sym a -> Sym a
    ** Sym a
    y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    forall a. Floating a => a -> a -> a
    (**) Sym a
    x String
    "**" Sym a
    y
        logBase :: Sym a -> Sym a -> Sym a
    logBase Sym a
    x Sym a
    y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    forall a. Floating a => a -> a -> a
    logBase Sym a
    x String
    "logBase" Sym a
    y
        sin :: Sym a -> Sym a
    sin = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    sin String
    "sin"
        tan :: Sym a -> Sym a
    tan = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    tan String
    "tan"
        cos :: Sym a -> Sym a
    cos = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    cos String
    "cos"
        asin :: Sym a -> Sym a
    asin = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    asin String
    "asin"
        atan :: Sym a -> Sym a
    atan = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    atan String
    "atan"
        acos :: Sym a -> Sym a
    acos = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    acos String
    "acos"
        sinh :: Sym a -> Sym a
    sinh = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    sinh String
    "sinh"
        tanh :: Sym a -> Sym a
    tanh = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    tanh String
    "tanh"
        cosh :: Sym a -> Sym a
    cosh = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    cosh String
    "cosh"
        asinh :: Sym a -> Sym a
    asinh = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    asinh String
    "asinh"
        atanh :: Sym a -> Sym a
    atanh = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    atanh String
    "atanh"
        acosh :: Sym a -> Sym a
    acosh = (a -> a) -> String -> Sym a -> Sym a
    forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
    unOp a -> a
    forall a. Floating a => a -> a
    acosh String
    "acosh"

    instance (RealFloat a, Show a) => RealFloat (Sym a) where
        floatRadix :: Sym a -> Integer
    floatRadix = a -> Integer
    forall a. RealFloat a => a -> Integer
    floatRadix (a -> Integer) -> (Sym a -> a) -> Sym a -> Integer
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Sym a -> a
    forall a. Show a => Sym a -> a
    unSym
        floatDigits :: Sym a -> Int
    floatDigits = a -> Int
    forall a. RealFloat a => a -> Int
    floatDigits (a -> Int) -> (Sym a -> a) -> Sym a -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Sym a -> a
    forall a. Show a => Sym a -> a
    unSym
        floatRange :: Sym a -> (Int, Int)
    floatRange  = a -> (Int, Int)
    forall a. RealFloat a => a -> (Int, Int)
    floatRange (a -> (Int, Int)) -> (Sym a -> a) -> Sym a -> (Int, Int)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Sym a -> a
    forall a. Show a => Sym a -> a
    unSym
        decodeFloat :: Sym a -> (Integer, Int)
    decodeFloat (Con a
    c) = a -> (Integer, Int)
    forall a. RealFloat a => a -> (Integer, Int)
    decodeFloat a
    c
        encodeFloat :: Integer -> Int -> Sym a
    encodeFloat Integer
    m Int
    e = a -> Sym a
    forall a. a -> Sym a
    Con (Integer -> Int -> a
    forall a. RealFloat a => Integer -> Int -> a
    encodeFloat Integer
    m Int
    e)
        exponent :: Sym a -> Int
    exponent (Con a
    c) = a -> Int
    forall a. RealFloat a => a -> Int
    exponent a
    c
        exponent Sym a
    _ = Int
    0
        significand :: Sym a -> Sym a
    significand (Con a
    c) = a -> Sym a
    forall a. a -> Sym a
    Con (a -> a
    forall a. RealFloat a => a -> a
    significand a
    c)
        scaleFloat :: Int -> Sym a -> Sym a
    scaleFloat Int
    k (Con a
    c) = a -> Sym a
    forall a. a -> Sym a
    Con (Int -> a -> a
    forall a. RealFloat a => Int -> a -> a
    scaleFloat Int
    k a
    c)
        scaleFloat Int
    _ Sym a
    x = Sym a
    x
        isNaN :: Sym a -> Bool
    isNaN (Con a
    c) = a -> Bool
    forall a. RealFloat a => a -> Bool
    isNaN a
    c
        isInfinite :: Sym a -> Bool
    isInfinite (Con a
    c) = a -> Bool
    forall a. RealFloat a => a -> Bool
    isInfinite a
    c
        isDenormalized :: Sym a -> Bool
    isDenormalized (Con a
    c) = a -> Bool
    forall a. RealFloat a => a -> Bool
    isDenormalized a
    c
        isNegativeZero :: Sym a -> Bool
    isNegativeZero (Con a
    c) = a -> Bool
    forall a. RealFloat a => a -> Bool
    isNegativeZero a
    c
        isIEEE :: Sym a -> Bool
    isIEEE = a -> Bool
    forall a. RealFloat a => a -> Bool
    isIEEE (a -> Bool) -> (Sym a -> a) -> Sym a -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Sym a -> a
    forall a. Show a => Sym a -> a
    unSym
        atan2 :: Sym a -> Sym a -> Sym a
    atan2 Sym a
    x Sym a
    y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    forall a.
    (Num a, Eq a) =>
    (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
    binOp a -> a -> a
    forall a. RealFloat a => a -> a -> a
    atan2 Sym a
    x String
    "atan2" Sym a
    y