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
The following file compiles here:
{-# LANGUAGE GeneralizedNewtypeDeriving, TypeFamilies #-}
class C a where g :: a
type family X
type instance X = Int
newtype NewX = NewX X deriving Num
instance C NewX where g = 43
A newtype
does just that--it defines a new type, while a type
defines a synonym. If you dont like a bunch of deriving clauses, one can always use the isomorphism with the underlying type
instance C NewX where
g = NewX 43
the reason type synonyms dont play nice with Instance declarations, is that functions (including type functions) only work in one direction. You can only pattern match on constructors, so newtype
allows you to introduce a new type constructor at zero runtime cost. In your problem, why not
newtype Row = Row {runRow :: FieldOf Col1 :&: FieldOf Col2}
instance Indexable Row where
empty = ixSet [ixFun $ (\x -> [ Col1 ^. (runRow x) ]) ]
I should note that in general GeneralizedNewtypeDeriving
is unsound. Doesn't mean you should avoid using it, but does imply what you want is probably impossible.
Edit (Question asker):
Better yet, no need to even change the data type Row
newtype Row = Row ( FieldOf Col1 :&: FieldOf Col2 )
instance Indexable Row where
empty = ixSet [ixFun $ (\(Row x) -> [ Col1 ^. x ]) ]