purescript-quotient
athanclark opened this issue · 2 comments
This is more of a conversation than it is an issue, but I think it might be a cool way of interfacing with array buffers:
Basically, in my branch that I'm going to submit, TypedArrays are represented with a typeclass, specifically something that indexes a userland type (like Int or Number (used to be UInt too, but more on that later...)) from a ArrayViewType - similar to Snoyman's mono-traversable package. Right now, most of the arrays' userland types are just Ints, with Number being used for Uint32Arrays, because the values are out of range for traditional purescript Ints.
I'm not using UInts anymore because they clearly encode values between 2^31 and 2^32 - 1 in
the negative range. This won't work for Uint32Arrays because the values it interprets are directly in the positive range (because Ints are just Numbers under-the-hood), therefore UInts are directly not actually in that range and all those values would get lost (probably assigned to 0). Something that I'd like to get added to purescript-math is fround :: Number -> Number in purescript-deprecated/purescript-math#21 and purescript-deprecated/purescript-math#19, which interestingly casts a Float64 to a Float32, but that's an aside on this aside.
Anyway, the conversation is this - purescript-quotient offers a nice newtype'd interface for modulo'ing values - https://pursuit.purescript.org/packages/purescript-quotient/2.0.0/docs/Type.Quotient#t:Canonical
I think it might be nice having something like (Int / Mod256) / Abs as a Byte, for instance. Maybe we should use purescript-typelevel and properly state the type as modulo an exponent of 2, like literally x :: Quotient Int D8 as ````mod2^8```, but that's even more of an aside. This could be really useful for pinning down instances of userland types of arraybuffers to exactly treat values as their bit capacity - a Uint8*Array would be(Int / Mod256) / Abs`, because we want values between `1` and `2^8 - 1`, and only positive values. `Int8` would also be just `Int / Mod128` for instance, because we want the negative values too.
What do you all think?
Can you elaborate on the problem with UInt?
I skimmed through your changes in that branch, wouldn't it make sense as a separate -arraybuffer-classes repo? I think we should in this one just have a thin wrapper on top of the JS API and provide mechanisms to upper level layers.
Let's say https://github.com/pure11/pure11 needs at some point to implement something like this in order to get some library that indirectly depends on this one running. I can see those changes happening in this repo and upper levels could be isolated from the process.
That's a really good point. Also... I wasn't paying attention: https://pursuit.purescript.org/packages/purescript-uint/4.0.2/docs/Data.UInt#v:toNumber there's mechanisms for this already I didn't look at.
As far as the thin wrappers go - most of the functionality is implemented with foreign functions of the form exports.foo = function(arr,x,y,z) {return a.foo(x,y,z)} - which is polymorphic over the typed array, and unsafely typed for the userland type actually used - something like foreign import foo :: forall arr u. ArrayView a -> u -> u -> u -> Effect Unit or something, that way the instance itself can type-caste the unsafe import to the correct userland type. If end-users use Uint8Array types and all that, the compiled output shouldn't be much different than having duplicate foreign imports of each.