mikeizbicki / subhask

Type safe interface for working in subcategories of Hask
BSD 3-Clause "New" or "Revised" License
418 stars 43 forks source link

Subhask vector type variadic function #51

Open bmabsout opened 8 years ago

bmabsout commented 8 years ago

I was looking a bit through the examples in the subhask github repo and I saw that a function called unsafeToModule that takes a list and creates the vector with a statically defined size is being used which is what I was doing when I was playing around with creating a sized vector but then I came across Variadic functions so I wrote one to be safer. the sized vector module I wrote is attached. (I actually had an issue where my list wasn't of the right size) SizedV.hs.zip

mkN is the function and can be used as such:

test :: SizedV Float _
test = mkN 1 2 3 4 5

with -XPartialSignatures enabled it is useful as it is not needed to say that _ is 5 it is automatically computed and editors can show you the value.

(Also I think the class Make can be simplified but I tried to write a simple instance and failed so I stole an old fixed size vector's implementation which uses peano numbers to encode length and modified it to my needs)

Edit: actually here's a simple version of the variadic function and it works as intended class Make n a r | r -> a where make :: SizedV n a -> r

instance Make n a (SizedV n a) where
    make x = x

instance (Make (n+1) a r,V.Storable a) => Make n a (a -> r) where
    make acc a = make (acc `snoc` a)

mkN :: (V.Storable a,Make 1 a r) => a -> r
mkN = make empty
mikeizbicki commented 8 years ago

Very interesting question! Thanks!

There are several reasons for the unsafeToModule function that the variadic function solution doesn't fix:

  1. The unsafeToModule function is easier to implement. But this is only a minor issue.
  2. Sometimes the length really can't be known at compile time. For example, maybe the vector's length is determined by a csv file. We still need a way to construct these vectors, and unsafeToModule lets us do that. The length of the vector is then represented by a Symbol at the type level, so we can still statically encode that different length vectors never get added together.

Furthermore, I think there is a simpler solution for what you're trying to do than variadic functions. Every free module with n dimensions is isomorphic to an n-tuple. So why not just provide functions/type classes that freely convert between the two types. Then something equivalent to your example code would read:

test :: SizedV Float _
test = mkN (1,2,3,4,5)

That's a very minor syntatic overhead, but is a bit more intuitive and gets you nicer error messages.

I'm open to counterarguments, but at this point variadic functions just seem like they'd complicate the code for little benefit.

bmabsout commented 8 years ago

yes for run time values use the unsafe version. And it is isomorphic to an n-tuple but can you have n-tuples in haskell? also isn't converting it a pain and bounded? also syntactically there is a problem with the variadic function approach: if you want to write negative numbers you either have to enable the negative literals extension or write (-1) for example where the tuple doesn't have that issue

mikeizbicki commented 8 years ago

GHC supports tuples up to size 64.

bmabsout commented 8 years ago

yes and I already have a 100 sized compile time vector that I am using, imagine you want a flat matrix that's 8x9 that would already exceed the limit. And you have to write an instance for every tuple no? that's alot of code, I wish ghc's tuple was more generic a bit like an type level list, actually now that I think about it that's exactly what you need and it might be much better than a variadic function , check this out https://hackage.haskell.org/package/type-list but you need one with the same type not the same kind

mikeizbicki commented 8 years ago

I guess it never occured to me that people might want such large compile time vectors, but you do have a point there.

Yes, an HList could serve this purpose well.

On Thu, Jul 7, 2016 at 12:09 AM, Bassel Mabsout notifications@github.com wrote:

yes and I already have a 100 sized compile time vector that I am using, image you want a flat matrix that's 8x9 that would already exceed the limit. And you have to write an instance for every tuple no? that's alot of code, I wish ghc's tuple was more generic a bit like an HList actually now that I think of it isn't HList exactly what you need? I havent looked at it too much but it might be

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mikeizbicki/subhask/issues/51#issuecomment-231000443, or mute the thread https://github.com/notifications/unsubscribe/ABAP1pGk6LuW_a4aoRcU5RKaTG3wEvGZks5qTKZCgaJpZM4JFzck .