Comments (14)
Generally, one concern core libraries have is whether adding some functionality will make it harder for non-JS backends to support that.
from purescript-math.
I think this library is in a weird place, but I don't have good answers for these questions either. I used to be a supporter of "it's just the Math object in JS", but that's muddied with ES6/2021 and the non-JS additions you mentioned. It seems like if we were going to move away from that, it should perhaps implement at least some things over our numeric classes rather than being specialised to Number
too.
I almost never find myself using this library, due to the nature of the things I work on these days, so my opinion probably shouldn't hold as much weight as those who are heavy users of it.
from purescript-math.
I think that in the past, having core libraries closely follow JS APIs made sense, but now that PureScript is more mature and especially now that there are alternative backends, we shouldn’t follow JS APIs too closely. For example, the strings and globals libraries have been moving away from closely following the JS API more recently. In my view the most important concern is whether we have a well designed library which allows PureScript users to do the things they need to do with a minimum of fuss.
I personally think that we could consider giving this library a similar treatment as globals. Most of the functions here could sensibly live in Data.Number, particularly the trig functions and constants and the logarithm stuff. One or two are obsoleted by more general functions which exist in Prelude - namely min
, max
, and abs
. The imul
function is unique in that it works on Int rather than Number, so that could go into Data.Int (or ideally into Int’s Semiring instance, but that’s slightly harder, see purescript/purescript#2980).
I am hesitant to introduce a type class for trig functions or logarithms, because it’s hard for me to imagine demand for them. I’m not aware of numeric types other than Number which would support those operations. Haskell needs the Floating class because it has both Float and Double, but we only have Number. It is slightly easier to imagine type classes for sqrt and rounding functions, but I think that can be addressed separately from the question of where these functions should live.
from purescript-math.
I agree with @hdgarrood regarding type classes. Many of the functions currently in Math would require new type classes. You can't write sqrt :: Field a => a -> a
because rationals are a field but do not support sqrt
. It seems silly to have type classes whose only instances are Number
and, even then, that instance isn't fully law abiding. Even min
and max
are different to the Data.Ord versions -- specifically in their handling of NaN. I think we preserve all these number-only versions in Data.Number until someone implements algebraic numbers or something where a type class would occur naturally.
from purescript-math.
From this discussion is sounds like:
(A) We should prioritize supporting multiple backends by minimizing the number of functions a new backend needs to implement
(B) We should move various functions into more sensible places, likely resulting in this library being deprecated at some point
I'd like to add a third priority, if I may:
(C) We should avoid doing anything that makes writing high-performance numeric code harder than it is now
These suggest the following steps:
- Move all constants to Data.Number.Constants as explicitly defined constants. So instead of
foreign import pi :: Number
we havepi = 3.141592653589793
. We would have to check that our constants are identical to the Javascript native ones but that should be easy. - Identify "core" math functions that we expect every backend to support and provide copies in Data.Number. I propose:
acos
,asin
,atan
,sin
,cos
,tan
,exp
,log
,pow
,sqrt
, andremainder
/%
. All of these are likely to be available in standard math libraries for most backends and would require fairly complex Purescript implementations. - Identify "branchless" functions that we require the backend to support. Although these could be implemented in terms of other functions, it would introduce an unnecessary (and slow) branch, whereas native implementations are likely to avoid that. I propose:
min
,max
,abs
andsign
. That's only four functions and backends are likely to have easily available versions. - Copy integer related functions into Data.Int. This would include
imul
,round
,ceil
andfloor
. The versions ofround
,ceil
andfloor
already in Data.Int are currently implemented in terms of Math. Only the Data.Int versions, with typeNumber -> Int
would be available after Math is deprecated. Users wantingNumber -> Number
versions would have to convert back fromInt
, which I think is fine.trunc
would be implemented in Purescript in terms ofceil
andfloor
in Data.Int - Implement all other functions as Purescript functions in terms of the functions above. Once
atan2
is implemented, Math could be depreciated. Functions from ES6 and others could be implemented at our leisure.
Together this would reduce the burden on new backends by reducing the number of functions they need to implement slightly versus the current situation (dropping all constants, atan2 and trunc) and dramatically versus the ES6-with-polyfills approach. By eventually depreciating Math it also removes a psychological association with Javascript. The functionality currently demanded in various issues and pull-requests would eventually be provided, albeit without a definite timetable.
from purescript-math.
I was going to suggest something about checking that atan(y/x)
behaves identically to atan2(y, x)
... but actually I think that's overkill - I'd be pretty surprised if there is an observable difference between the two that anyone is depending on, and if they are I'd suggest a separate JS-specific library / project-local FFI function can be introduced to deal with that again.
So yeah, the proposal above sounds good to me!
from purescript-math.
I agree, except:
- I don’t think we should remove the
Number -> Number
rounding functions; I think they are useful often enough that they are worth providing, and also the range of Number is much larger than that of Int, so it’s not possible to recover the same behaviour for numbers outside of the Int range. - I think
atan2
should be one of the “core” math functions, because you’d need to branch to implement it in terms ofatan
.atan2(y, x)
is not the same asatan(y/x)
because the latter can’t return angles in all four quadrants; see https://stackoverflow.com/a/12011762
Can you please list the other “non-core” functions which we’d implement in PureScript, just to make sure we are on the same page?
from purescript-math.
Oh also, I think constants don’t need to go in a separate module. I think it would be annoying to have to add another import just to use pi, so I’d personally rather they just go in Data.Number.
from purescript-math.
Ah, great point on atan2
, I had a dormant inclination there was something special about it, hence my earlier comment, but couldn't dredge up why it actually mattered.
from purescript-math.
Ok. I agree we can:
- Have
ceil
,floor
andround
in Data.Number and have the Data.Int versions use those - Put the constants in Data.Number directly rather than Data.Number.Constants
"Non-core" functions would come in three phases:
- Those necessary to be able to deprecate purescript-math. That is just
atan2
in Data.Number (if we go that way) andtrunc
in Data.Int. - Those necessary to replicate the functionality of the new ES6 functions attached to the Math object. That is the hyperbolic trignometric functions (
acosh
,asinh
,atanh
,cosh
,sinh
,atanh
), logs to other bases (log2
andlog10
) and numerical stability functions (hypot
,log1p
andexpm1
). I don't see a need forcbrt
,clz32
orfround
but they could be implemented if someone is interested (and being able to leave them out is an advantage of moving away from the "it's just the Math object in JS" approach). The repopurescript-math-es6
has Javascript polyfills taken from MDN for all these functions which could be fairly easily converted to Purescript but I'd like to take the process slow and ensure that only very robust and stable versions are implemented. - Any other functions that sensibly fit in Data.Number. I would suggest the log-gamma function, the error function, the inverse error function and the complementary error and inverse error functions. These all have type
Number -> Number
and are general enough that they probably belong in Data.Number. I would oppose putting the cdf or pdf of any particular probability distribution in Data.Number, however.
from purescript-math.
Wikipedia suggests a branchless implementation of atan2
as
((sign x) ^ 2) * atan(y / x) + (1 - sign y + (sign y) ^ 2) * pi / 2.0
.
I haven't checked this in detail yet.
Can we leave atan2
in the category of "branchless Purescript if a robust implementation is available, provided by the backend otherwise". I'll try to come up with a PR at some point just for a branchless atan2
and you guys can accept or reject it at that point based on its merits.
Or is that not worth it and we just punt it off to the backend?
from purescript-math.
Screw it. The Wikipedia approach gives atan2(0, 0) == NaN
whereas both the Node and Chrome versions give atan2(0,0) == 0
. Building an exactly matching branchless version will be a pain so I recant and now agree with @hdgarrood that atan2
should be implemented by the backend.
from purescript-math.
Summarizing #31 (comment), it seems that to fully deprecate this repo, we need to
Add/change the following to numbers
:
ceil
,floor
, andround
- done in purescript/purescript-numbers#18atan2
(needed to deprecatepurescript-math
) - done in purescript/purescript-numbers#18- Replicate ES6 functions added to Math object: (all of the functions below have not yet been done in purescript/purescript-numbers#18)
- add hyperbolic trignometric functions:
acosh
,asinh
,atanh
,cosh
,sinh
,atanh
- add logs to other bases:
log2
andlog10
- add numerical stability functions:
hypot
,log1p
andexpm1
- add hyperbolic trignometric functions:
Add/change the following to integers
:
ceil
,floor
, andround
, which use thenumbers
version before convert back toInt
trunc
(needed to deprecatepurescript-math
) - this needs to be added in a new PR
The rest is something that could be done but isn't needed.
Functions that could belong in numbers
:
- log-gamma function, error function, inverse error function, the complementary error function, and inverse error function.
Up for grabs / could be implemented by other libraries:
cbrt
,clz32
orfround
- cdf or pdf of any particular probability distribution
from purescript-math.
All code in math
has been ported to purescript-numbers
and purescript-integers
from purescript-math.
Related Issues (9)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from purescript-math.