As I was working on changing division behaviour and adding new checked versions, I noticed that there were a few functions that I didn't see in the Num module: namely exp (the exponential function), ln (the natural logarithm), and the hyperbolic functions (and their inverses). I personally think they – or at least exp and ln – are quite fundamental mathematical functions, and deserve a place in the Num module.
So I propose:
exp : Frac a -> Frac a
ln : Frac a -> Frac a
lnChecked : Float a -> Result (Float a) [ LogNeedsPositive ]*
-----Non-essential---------
sinh : Frac a -> Frac a
cosh : Frac a -> Frac a
tanh : Frac a -> Frac a
asinh : Frac a -> Frac a
acosh : Frac a -> Frac a
atanh : Frac a -> Frac a
What do you think?
Do we want/have e in library, if so, they can just be log and power base e
Though I guess a wrapper is fine too
I'm assuming that the current log we have is of base 2 – so users would have to perform a change of base themselves to use the natural logarithm. e by itself is rarely ever useful, and e to the power of a non-natural number is really an abuse of notation since we're in reality referring to the Taylor series of e^x defined as exp.
Most languages have exp instead of e, and if users really want e they can do exp(1.0). Sticking with convention seemed like the right thing to do.
I'm also a fan of having an explicit ln function, since most languages have base-e log and base-2 log2, which has always felt non-sensical to me since the use of logarithms in computer science is heavily biased towards base-2 logarithms, and in maths base-e logarithms are usually written as ln.
Now that I say it out loud though I'm not sure if Roc's log is base-2 or base-10 :thinking:
Actually looks like it's base-10. The most common use-cases are base-2, base-10, and base-e, so I think those should be clearly separated into their own functions to remove any ambiguity. What do you think?
Our current log is the natural logarithm
» Num.log 2.71
Ok 0.9969486348916096 : Result (Float *) [ LogNeedsPositive ]*
Got it! What do you think about instead having Num.log2, Num.log10, and Num.ln / Num.naturalLog ?
It seems pretty common in programming for an un-qualified "log" function to be base-e (naturally). We'll probably want a Num.log2 and a Num.log10 at some point? Or maybe for non-e cases a Num.logBase base n (I'm not sure what a good naming is for it)?
e by itself is rarely ever useful, and e to the power of a non-natural number is really an abuse of notation since we're in reality referring to the Taylor series of e^x defined as exp.
I don't think this is true. In probability you take e to power of non-naturals all the time. Euler's number is lot more useful than in just the series definition sense
I think log2, log10, etc. make sense. there are already llvm intrinsics for those (not sure if they're hardware instructions) and this wasm implementation seems to just do a base conversion, which seems fine save loss of precision
I've done more maths than programming in my short lifespan so I'm definitely biased towards an explicit "natural log" instead of a log with implicit base e. I've just always felt that log by itself feels incomplete and almost esoteric to beginner programmers like me not that long ago. log2 and log10 sound great though!
@Ayaz Hafiz what do you think about exp then? I see your point about e by itself having just as much value, but exp would offer a more succinct API in general I think.
I'm the same as you. And sure, you never really write a naked "log", you write "ln" everywhere.
Personally I'm of the opinion that it's more helpful to see what people use first and decide what to add based on usage patterns. It's easier to expand a public API than it is to restrict it.
So what do you think should be added / changed then? Or should it stay as it is for now
I would rather have logE to match log2 than have ln or naturalLog
Though I definitely prefer just log
Last updated: Jun 16 2026 at 16:19 UTC