log, exp, (**), and non-negative real numbers

Hi, I'm working with some classes that handle probabilities in terms of their log or log-odds. Such classes only handle non-negative real numbers. For example, from Numeric.Log: newtype Log a = Exp { ln :: a } Since the log of a positive number can be negative, we don't want to use the same type to hold the number and its logarithm. Standard functions exp, log, and (**) are awkward because they all assume that numbers and their powers have the same type: log,exp :: a -> a (**) :: a -> a -> a In comparison the ln function from Numeric.Log has a different signature that allows a number and its logarithm to have different types: ln :: Log a -> a Exp :: a -> Log a In order to address this, I have tried defining a type class Pow: class Fractional a => Pow a where pow :: a -> Double -> a ln :: a -> Double expTo :: Double -> a Probably I should replace "Double" here by a type variable b, but I have not done so yet. I'm mostly interested in abstracting over the type of non-negative number, because I have another type Prob that is designed to handle numbers like 1e - 100000, and 1.0 - 1e-100000. data Prob = Zero | Odds Double | One | IOdds Double | Infinity -- store probability in terms of log odds = log (p/(1-p)) Q1. Does anybody know of an existing Haskell module that implements something like the Pow class above? Also, it would be nice (notationally) if I could use log, exp, and (**) instead of ln, expTo, and pow. In theory we could factor out log, exp, (**), sqrt, and logBase from Floating into a new superclass of Floating, so that Floating only contains trig and hyper-trig functions. But I suspect this will not work because the methods in class Pow are more ambiguous. For example, if (x :: Double) then you can do (expTo x :: Prob) and (expTo x :: Log Double) and they will yield different types. Q2. Does anybody have a suggestion for a nicer design? Thanks! -BenRI

If you end up coming up with a nice library design, you may want to generalize these operations from Double-valued logarithms to conversions between a Lie group and its corresponding Lie algebra. Exp/ln on all/positive real numbers is a special case of exp/ln on a lie algebra/group. Maybe worth checking if there already exists a package for working with lie groups in a nicely-typed way. If there's not a haskell one, I bet one of the theorem prover languages (coq, agda, idris) has one. Best, Will

On Tue, Apr 04, 2023 at 05:50:41AM -1000, Will Yager wrote:
If you end up coming up with a nice library design, you may want to generalize these operations from Double-valued logarithms to conversions between a Lie group and its corresponding Lie algebra.
Abstracting from the positive reals to (possibly non-abelian, complex?) Lie groups is a rather steep generalisation. Is there no useful intermediate step? Or is it the case here that the most general form is also the simplest (does away with inessential details that distract from the core concepts)? I do recall that for me at one point Calculus in Banach spaces was easier to understand than Calculus in R^3. The generalisation was cleaner. -- Viktor.

I like the Lie algebra suggestion, but I doubt that, out of the box, it would support the tiny probabilities like 1e-100000 that Benjamin supports.
On Tuesday, April 4, 2023 at 11:51:11 AM EDT, Will Yager
participants (4)
-
Benjamin Redelings
-
Mark McConnell
-
Viktor Dukhovni
-
Will Yager