Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic derivation of Data.Vector.Unbox with associated type synonyms

I have a datatype

newtype Zq q = Zq (IntType q)

where 'q' will be an instance of the class

class Foo a where
   type IntType a

and 'IntType' is just the underlying representation (i.e. Int, Integral, etc) associated with 'q'.

I want to make Zq an instance of Data.Vector.Unbox. We are currently manually deriving Unbox using about 50 lines of trivial code as suggested in the link above. We will be making several different types 'Unbox' in our code, so writing 50 lines for each type is not appealing.

I found two alternatives here. One alternative is to use this package which uses Template Haskell to derive instances of Unbox. The TH code would look like:

derivingUnbox "Zq"
  [d| instance (Foo q, U.Unbox (IntType q)) => Unbox' (ZqBasic q) (IntType q) |]
  [| \ (Zq x) -> x |]
  [| \ x -> Zq x |]

The problem is, I can't define instances using associated type synonyms (or can I??)

[A related question: Why does TypeSynonymInstances, an extension implied by FlexibleInstances, not allow associated type synonym instances? Is this somehow fundamentally a different beast?]

My current solution to that problem is to redefine Zq as

newtype Zq q i = Zq i

and then add the equality constraint

i~(IntType q)

in every instance involving (Zq q i), which isn't very elegant. My (working) Unbox derivation becomes

derivingUnbox "Zq"
  [d| instance (U.Unbox i, i~IntType q, Foo q) => Unbox' (Zq q i) i |]
  [| \ (Zq x) -> x |]
  [| \ x -> Zq x |]

I feel like I should be able to accomplish this without resorting to explicitly exposing the type 'i'. All I've done is moved it from an associated type synonym to an explicit parameter with equality constraints. Why is this "fundamentally" a different (and apparently safer) approach? Is there some way I can avoid adding the type parameter 'i' and still get automatic Unbox derivation?

Extra type parameter aside, I'm having trouble using the TH package to derive Unbox for (Vector r), that is, I want to make an Unbox Vector of Unbox Vectors. My attempt is something like:

newtype Bar r = Bar (Vector r)

derivingUnbox "Bar"
  [d| instance (Unbox r) => Unbox' (Bar r) (Vector r) |]
  [| \ (Bar x) -> x |]
  [| \ x -> Bar x |]

but I get (lots of) errors like:

`basicUnsafeFreeze` is not a (visible) method of class `Data.Vector.Generic.Base.Vector`

I'm not sure why it can't find this method, when it works just fine for my Zq type.


The second approach listed above is using the extension GeneralizedNewtypeDeriving. The biggest problem I see with this approach is that I have some actual Data (rather than Newtype) that I need to be Unbox. However, just using the extension, I should be able to write

newtype Zq q = Zq (IntType q) deriving (Unbox, M.MVector MVector, G.Vector Vector)

or at least

newtype Zq q i = Zq i deriving (Unbox, M.MVector MVector, G.Vector Vector)

The first leads to the errors:

No instance for (Unbox (IntType q)) arising from the `deriving` clause of a data type declaration
No instance for (M.MVector MVector (IntType q)) ""
No instance for (G.Vector Vector (IntType q)) ""

and the second gives:

No instance for (M.MVector MVector i) ""
No instance for (G.Vector U.Vector i) ""

I'm not sure why it can't derive these instances, as the post above leads me to believe it should be able to. Perhaps I could get away with using the associated type synonym with GeneralizedNewtypeDeriving? (This still (probably) doesn't solve my problem when I need to derive Unbox for 'data's.)

Thanks for your help!

like image 571
crockeea Avatar asked Jul 09 '12 16:07

crockeea


1 Answers

I've changed the syntax in 4820b73, so you should be able to do what you want now:

derivingUnbox "Complex"
    [d| (Unbox a) ⇒ Complex a → (a, a) |]
    [| \ (r :+ i) → (r, i) |]
    [| \ (r, i) → r :+ i |]

I've also fixed the “xyz is not a (visible) method…” errors in fe37976, although it was possible to work around it with:

import qualified Data.Vector.Generic
import qualified Data.Vector.Generic.Mutable

Out now on Hackage. CC: @reinerp

like image 64
liyang Avatar answered Jan 12 '23 19:01

liyang