Lets say we have the following code:
class C t where
g :: t
instance C Int where
g = 42
Simple. We can also define functions on Int, like so:
f1 :: Int -> Int
f1 x = x * x
I've been working with type families, in particular because Data.Has
uses them, and I want to insert them into an IxSet
.
But here I'm going to present a simplified example. Lets say we want to define a new type X
, that is similar to an Int. We could do this:
type family X
type instance X = Int
We can then define functions on X
like so:
f2 :: X -> X
f2 x = x * x + 1
No problems so far. Now lets try to define an instance C X
, like we did for C Int
:
instance C X where
g = 43
Uh oh, now we have the following error:
Illegal type synonym family application in instance:
X
In the instance declaration for'C X'
Now lets try something a bit different:
newtype NewX = NewX X
instance C NewX where
g = 43
Now we've got another error, namely:
No instance for
(Num NewX)
arising from the literal'43'
It seems like the newtype
keyword eliminates any information about what classes the previous class belonged too. However, it also seems I can't avoid newtype
, as I can't use type families in instance definitions.
Is there a better way to do this without having to rewrite instance definitions with additional explicit instances mentions which otherwise would be inferred?
Background information:
The reason why I need this to work is the following:
import Data.Has
import Data.IxSet
data Col1 = Col1; type instance TypeOf Col1 = Text
data Col2 = Col2; type instance TypeOf Col2 = Text
type Row = FieldOf Col1 :&: FieldOf Col2;
instance Indexable Row where
empty = ixSet [ixFun $ (\x -> [ Col1 ^. x ]) ] -- Maybe add some more indexes later
This fails with:
Illegal type synonym family application in instance:
Row
In the instance declaration for'Indexable Row'
Making Row
a newtype
causes the following error:
No instance for (Contains (Labelled Col1 Text) Row) arising from a use of `^.' Possible fix: add an instance declaration for (Contains (Labelled Col1 Text) Row)
The only way I can work around this is by adding a long deriving clause as follows:
newtype Row = Row (FieldOf Col1 :&: FieldOf Col2)
deriving
(
Contains (Labelled Col1 Text), -- Add this for every column
Contains (Labelled Col2 Text) -- ...
)
Even something which allows me to "typedef" Contains (Labelled x (TypeOf x))
to say HasCol x
would be helpful.
X
is a synonym forInt
(kind of). However you just can use the original type instead (Int
in this case). Perhaps a more real example would clarify the picture. – n. 1.8e9-where's-my-share m.Row
yourself and writing an instance for that type, instead? – Daniel Wagner-XTypeSynonymInstances -XFlexibleInstances
might be what you need. – n. 1.8e9-where's-my-share m.