假设我们有以下代码:
class C t where
g :: t
instance C Int where
g = 42
简单的。我们还可以在 Int 上定义函数,如下所示:
f1 :: Int -> Int
f1 x = x * x
我一直在使用类型系列,特别是因为Data.Has
使用它们,并且我想将它们插入到IxSet
.
但在这里我将展示一个简化的例子。假设我们要定义一个X
类似于 Int 的新类型。我们可以这样做:
type family X
type instance X = Int
然后我们可以像这样定义函数X
:
f2 :: X -> X
f2 x = x * x + 1
到目前为止没有问题。现在让我们尝试定义一个实例C X
,就像我们为C Int
:
instance C X where
g = 43
哦哦,现在我们有以下错误:
Illegal type synonym family application in instance:
X
在实例声明中为'C X'
现在让我们尝试一些不同的东西:
newtype NewX = NewX X
instance C NewX where
g = 43
现在我们遇到了另一个错误,即:
(Num NewX)
没有从字面上产生的例子'43'
关键字似乎也newtype
消除了有关前一个类所属的类的任何信息。但是,我似乎也无法避免newtype
,因为我不能在实例定义中使用类型族。
有没有更好的方法来做到这一点,而不必用额外的显式实例提及重写实例定义,否则会被推断出来?
背景资料:
我需要这个工作的原因如下:
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
这失败了:
Illegal type synonym family application in instance:
Row
在实例声明中为'Indexable Row'
制作Row
anewtype
会导致以下错误:
(Contains (Labeled Col1 Text) Row) 没有因使用 `^.' 而产生的实例 可能的解决方法:为 (Contains (Labeled Col1 Text) Row) 添加一个实例声明
我可以解决这个问题的唯一方法是添加一个长推导子句,如下所示:
newtype Row = Row (FieldOf Col1 :&: FieldOf Col2)
deriving
(
Contains (Labelled Col1 Text), -- Add this for every column
Contains (Labelled Col2 Text) -- ...
)
即使是允许我“typedef”Contains (Labelled x (TypeOf x))
说的东西HasCol x
也会有所帮助。