<div dir="ltr">Hello Jake,<div><br></div><div>Many libraries implement this "array of structures -> structure of arrays" type of transformation, including for example the 'accelerate' library. I'm however only aware of one that does it for good old vectors: <a href="https://hackage.haskell.org/package/hybrid-vectors" target="_blank">https://hackage.<wbr>haskell.org/package/hybrid-<wbr>vectors</a></div><div><br></div><div>I don't think it implements any Generic-deriving mechanism for making this work on user-specified types without any effort. This could be a pretty nice addition though :)</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 25, 2017 at 12:43 AM, Jake Waksbaum <span dir="ltr"><<a href="mailto:jake.waksbaum@gmail.com" target="_blank">jake.waksbaum@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><span>I am trying to create a data type that is an vector of values, but internally uses an unboxed vector when possible and a boxed array otherwise. If this already exists, let me know. For example, any easily unboxed type is stored in an unboxed array, but also any type that is a product type of only easily unboxed types like (Int, Int) is stored in multiple unboxed arrays. I don’t think there is a smart way of doing this for sum types, so those are stored in boxed arrays.<br><br></span>I’m trying to create a typeclass<div><span><br></span><div><span style="font-size:14px"><font face="Iosevka"><div>class VectorElement a where</div><div>  data Vector a</div><div>  replicate :: Int -> a -> Vector a</div><div>  length :: Vector a -> Int</div></font></span><div><span><br>to represent things that can be stored in Vectors. I can then implement it for specific types that I know can be stored in unboxed vectors:<br><div><br></div></span><div><span><font face="Iosevka" style="font-size:14px">instance VectorElement Int where<br>  newtype Vector Int = VectorInt (U.Vector Int)<br>                     deriving Show<br>  replicate len x = VectorInt $ U.replicate len x<br>  length (VectorInt v) = U.length v</font><br><br></span></div><span><div><span>I also want to automatically derive instances of this class for other types using the Generic typeclass. Ideally these instances would be the most efficient possible, so that for example the instance for (Int, Int) used two unboxed arrays but the instance for Maybe Int uses a boxed array. To that end I created another typeclass and wrote instances for the Generic data constructors:<br><br><div><font face="Iosevka" style="font-size:14px">class VectorElementG (r :: * -> *) where</font></div><div><font face="Iosevka" style="font-size:14px">  data VectorG r</font></div><div><font face="Iosevka" style="font-size:14px">  replicateG :: Int -> r a -> VectorG r</font></div><div><font face="Iosevka" style="font-size:14px">  lengthG :: VectorG r -> Int</font></div><div><br></div><div><font face="Iosevka" style="font-size:14px">instance VectorElementG V1 where</font></div><div><font face="Iosevka" style="font-size:14px">  data VectorG V1</font></div><div><font face="Iosevka" style="font-size:14px">  replicateG = undefined</font></div><div><font face="Iosevka" style="font-size:14px">  lengthG = undefined</font></div><div><font face="Iosevka" style="font-size:14px"><br></font></div><div><font face="Iosevka" style="font-size:14px">instance VectorElementG U1 where</font></div><div><font face="Iosevka" style="font-size:14px">  newtype VectorG U1 = VectorGUnit Int</font></div><div><font face="Iosevka" style="font-size:14px">  replicateG i U1 = VectorGUnit i</font></div><div><font face="Iosevka" style="font-size:14px">  lengthG (VectorGUnit i) = i</font></div><div><font face="Iosevka" style="font-size:14px"><br></font></div><div><font face="Iosevka" style="font-size:14px">instance VectorElement a => VectorElementG (K1 i a) where</font></div><div><font face="Iosevka" style="font-size:14px">  newtype VectorG (K1 i a) = VectorGK (Vector a)</font></div><div><font face="Iosevka" style="font-size:14px">  replicateG i (K1 x) = VectorGK $ replicate i x</font></div><div><font face="Iosevka" style="font-size:14px">  lengthG (VectorGK v) = length v</font></div><div><font face="Iosevka" style="font-size:14px"><br></font></div><div><font face="Iosevka" style="font-size:14px">instance (VectorElementG r1, VectorElementG r2) => VectorElementG (r1 :*: r2) where</font></div><div><font face="Iosevka" style="font-size:14px">  data VectorG (r1 :*: r2) = VectorGProd (VectorG r1) (VectorG r2)</font></div><div><font face="Iosevka" style="font-size:14px">  replicateG i (a :*: b) = VectorGProd (replicateG i a) (replicateG i b)</font></div><div><font face="Iosevka" style="font-size:14px">  lengthG (VectorGProd v _) = lengthG v</font></div><div><font face="Iosevka" style="font-size:14px"><br></font></div><div><font face="Iosevka" style="font-size:14px">instance VectorElement ((r1 :+: r2) p) where</font></div><div><font face="Iosevka" style="font-size:14px">  newtype Vector ((r1 :+: r2) p) = VectorSum (V.Vector ((r1 :+: r2) p))</font></div><div><font face="Iosevka" style="font-size:14px">  replicate i x = VectorSum $ V.replicate i x</font></div><div><font face="Iosevka" style="font-size:14px">  length (VectorSum v) = V.length v</font></div><div><font face="Iosevka" style="font-size:14px"><br></font></div><div><font face="Iosevka" style="font-size:14px">instance VectorElementG f => VectorElementG (M1 i c f) where</font></div><div><font face="Iosevka" style="font-size:14px">  newtype VectorG (M1 i c f) = VectorGMeta (VectorG f)</font></div><div><font face="Iosevka" style="font-size:14px">  replicateG i (M1 f) = VectorGMeta $ replicateG i f</font></div><div><font face="Iosevka" style="font-size:14px">  lengthG (VectorGMeta v) = lengthG v</font></div><div><br></div><br>I’m not sure if these are correct, especially the one for :+:. I want basically base cases to be any type that already has an instance of VectorElement or a sum type which is automatically boxed, and the recursive case to basically just use parallel vectors for product types.</span></div></span><span><div><span><br></span></div></span><div><span>I think this sort of worked insofar as it allowed me to write an instance for tuples:</span></div><div><span><br></span></div><div><span><div><font face="Iosevka" style="font-size:14px">instance (VectorElement a, VectorElement b) => VectorElement (a,b) where</font></div><div><font face="Iosevka" style="font-size:14px">  newtype Vector (a, b) = VectorTuple (VectorG (Rep (a, b)))</font></div><div><font face="Iosevka" style="font-size:14px">  replicate i x = VectorTuple $ replicateG i (from x)</font></div><div><font face="Iosevka" style="font-size:14px">  length (VectorTuple v) = lengthG v</font></div><div><span><br></span></div>Ideally, however, the compiler would automatically derive this instance using the Generic instance. Is there a way to do that also?</span></div><div><span><br></span></div><div><span>I would welcome any thoughts on this entire idea and approach.</span></div><div><span><br></span></div><div><span>Thanks,</span></div><div><span>Jake Waksbaum</span></div></div></div></div></div><br>______________________________<wbr>_________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a><br>
Only members subscribed via the mailman list are allowed to post.<br></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">Alp Mestanogullari</div>
</div>