I have a data type
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 base view (i.e., Int, Integral, etc.) associated with q.
I want to make Zq an instance of Data.Vector.Unbox . Currently, we manually output Unbox using about 50 lines of trivial code, as suggested in the link above. We will do several different types of "Unbox" in our code, so writing 50 lines for each type is not attractive.
I found two alternatives here . One option is to use this package , which uses Template Haskell to output Unbox instances. The TH code would look like this:
derivingUnbox "Zq" [d| instance (Foo q, U.Unbox (IntType q)) => Unbox' (ZqBasic q) (IntType q) |] [| \ (Zq x) -> x |] [| \ x -> Zq x |]
The problem is that I cannot define instances using the associated type synonyms (or can I?)
[Related question: Why TypeSynonymInstances , an extension implied by FlexibleInstances, does not allow instances of a type synonym related ? Is this somehow a fundamentally different beast?]
My current solution to this problem is to redefine Zq as
newtype Zq qi = Zq i
and then add an equality constraint
i~(IntType q)
in each case, including (Zq qi), which is not very elegant. My (working) Unbox output becomes
derivingUnbox "Zq" [d| instance (U.Unbox i, i~IntType q, Foo q) => Unbox' (Zq qi) i |] [| \ (Zq x) -> x |] [| \ x -> Zq x |]
It seems to me that I could accomplish this without resorting to explicit exposures of the "i" type. All I did is transfer it from the associated type synonym to an explicit parameter with equality constraints. Why is this βfundamentallyβ different (and, apparently, safer)? Is there a way to avoid adding a parameter of type βiβ and still get automatic Unbox output?
Optional parameter parameter, I am having problems using the TH package to display Unbox for (Vector r), that is, I want to make 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 (many) errors, for example:
`basicUnsafeFreeze` is not a (visible) method of class `Data.Vector.Generic.Base.Vector`
I'm not sure why he cannot find this method when it works great for my Zq type.
The following approach, described above, uses the GeneralizedNewtypeDeriving extension. The biggest problem that I see with this approach is that I have some factual data (not Newtype) that I need for 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 qi = Zq i deriving (Unbox, M.MVector MVector, G.Vector Vector)
The first leads to 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 he cannot get these instances, as the above post makes me believe that he should be capable. Maybe I can use the associated type synonym with GeneralizedNewtypeDeriving? (This still (maybe) does not solve my problem when I need to get Unbox for "data".)
Thanks for your help!