Proposal: Add log1p and expm1 to GHC.Float.Floating

Edward Kmett ekmett at gmail.com
Mon Apr 21 00:20:52 UTC 2014


The proposal is worded the way it is to get a strict monotonic improvement
over the status quo.

With them in the class it becomes possible to get the instances fixed. With
them outside of the class in some needless extra hair-splitting class added
on later like we have to use today, then someone who would otherwise just
use them is needlessly hoist on the dilemma of using a more restrictive
class and just accepting the fact that they can't work with third party
numeric types for the most part at all, or reverting to the poor version of
the numerics to widen their audience.

This leads to the equivalent of needless divisions between 'traverse' vs.
'mapM' forever.

With defaults you are never worse off than you are today, but defaults you
*always* have to worry about whether you should use them.

Let's look at it another way.

By putting in defaults the costs of the proposal are borne by the people
who want to use the new feature.

Moreover, if we should decide to adopt wren's half-suggestion of continuing
to expand support for other numerical primitives that have broad support we
could do so without  great deal of fanfare, and the handful of people who
actually do numeric computation can talk to the handful of people who write
numeric instances that high up the foodchain to get the important ones
fixed in packages like vector-space, linear, diagrams, etc.

Without defaults everyone who ever wrote a Floating instance by hand would
need to know about log1p or wren's log1mexp and they would be forced into
using CPP in their code to work around a feature they don't care about and
if they couldn't be bothered then the user who wanted a bit of extra
precision now just starts crashing. The risk averse would simply take the
path with worse precision or get shoved back into the world of code
duplication and 'mapM' vs 'traverse'.

I know for me personally it would force me to double the amount of numeric
code I write, just to maximize my audience. I really don't want to go
there. I just want to be able to call the function I mean, and to be able
to talk to the right people to make it do the right thing.

-Edward


On Sun, Apr 20, 2014 at 7:32 PM, John Lato <jwlato at gmail.com> wrote:

> On Sat, Apr 19, 2014 at 5:49 AM, Edward Kmett <ekmett at gmail.com> wrote:
>
>> With the defaults the code is never worse than it is forced to be right
>> now and users do not need to create CPP blocked code to work around this
>> addition.
>>
>
> I usually like defaults, and avoiding CPP is good, however with the
> defaults users will expect better code than they get.  We aren't doing
> anyone any favors by introducing the possibility of silent floating-point
> precision loss from 'exp1m'.  An "error" default would be better.
>
> Besides, the code would be worse than it's forced to be now.  At least now
> users who care about this run headlong into the issue.  If we provide exp1m
> and log1p, users who use those functions should get the advertised
> behavior, not loss of precision (I realize not all types would lose
> precision, but some will).
>
>
>>
>> Without the defaults this becomes a much bigger request, as I'd be asking
>> _every_ author of Floating to add CPP to their packages for a feature they
>> never heard of and probably will never use, and in that situation we'd have
>> to export it from Prelude.
>>
>
> It's perfectly fine to leave some methods blank; IMHO the resulting
> run-time error is better than an incorrect default.  Plus, it's useful for
> library authors to know that the class has changed; if a default is
> provided everything will build properly and there is no compile-time
> indication that library authors should adjust their code.
>
> Originally I was +1 for everything except the defaults, but I'm
> reconsidering.  If this is something that most Floating instance authors
> don't know about and probably won't ever use, do these functions really
> belong in that class?  Why not make a separate class for fused algorithms?
>
> John L.
>
>
>
>>
>> -Edward
>>
>>
>> On Sat, Apr 19, 2014 at 5:42 AM, Scott Turner <2haskell at pkturner.org>wrote:
>>
>>>  On 2014-04-17 15:08, Edward Kmett wrote:
>>>
>>>  On Thu, Apr 17, 2014 at 2:48 PM, Henning Thielemann <
>>> schlepptop at henning-thielemann.de> wrote:
>>>
>>>> I think one should add default implementations. They don't have an
>>>> numerical advantage but they save programmers from code breakage.
>>>
>>>
>>>  I included the default definitions in code snippet in the proposal, so
>>> user code that remains unaware of them would be unaffected, while packages
>>> like compensated, or a wrapper around libqd could implement them as needed.
>>>
>>>  expm1 :: Floating a => a -> a
>>> expm1 x = exp x - 1
>>>
>>>  log1p :: Floating a => a -> a
>>> log1p x = log (1 + x)
>>>
>>> On the contrary, code that explicitly uses these functions is likely to
>>> need the precision. Defaults would cause subtle breakage.
>>>
>>> -- Scott
>>>
>>
>>
>> _______________________________________________
>> Libraries mailing list
>> Libraries at haskell.org
>> http://www.haskell.org/mailman/listinfo/libraries
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/libraries/attachments/20140420/abb5788f/attachment-0001.html>


More information about the Libraries mailing list