我在不同的模块中有三个数据声明:
data Data1 = Data1
{ id :: UUID
, field2 :: String
, field3 :: Int
}
data Data2 = Data2
{ id :: UUID
, field1112 :: String
, field4433 :: String
}
data Data3 = Data3
{ id :: UUID
, field22 :: Double
, field344 :: Int
}
一个班级宣言:
class MyClass1 a where
method1 ....
如何为MyClass1
指定约束,以便Data1, Data2 and Data3
只能MyClass1
实例化id
因为所有人都有字段-- in the different module
class MyDataBase a where
id :: a -> UUID
-- in the module Data1.hs
instance MyDataBase Data1 where
id d1 =
-- in the module Data2.hs
-- and so on....
class (MyDataBase a) => MyClass1 a where
method1 .... = -- calling
?
我尝试了下面这个,但它似乎对我不对,我得到了错误:
$scope
答案 0 :(得分:4)
所以MyClass1只能实例化Data1,Data2和Data3,因为它们都有字段ID?
那些你不知道的类型也有那个领域?
一般来说,你可以使用Lens完成类似的事情(常规的Haskell记录是IMHO不可用的);如果您为字段_Data1Id
和_Data2Id
(可自定义)命名,则会为HasId
提供id
个Data1
课程和Data2
类的实例makeFields
。然后,您可以进一步使用该类作为约束。
当然,您不必使用UndecidableInstances
,您可以自己编写实例。不知道为什么你这样做。
你没有指明你得到了什么错误,但我突然失去了class A a where aOp :: a -> Int
class B a where bOp :: a -> Int
data C = forall a. B a => C a
instance A C where aOp (C a) = bOp a
。以下是如何解决“约束不小于实例头”的错误:
string customerNameTB = customerNameTextbox.Text;
customerNameTB=customerNameTB.Replace("'", "''");
customerNameTB=customerNameTB.Replace("'''", "''");
这将允许你在A语境中使用满足B的任何类型(但正如Carsten指出的那样,它也是一种反模式)。
答案 1 :(得分:0)
你不想这样做。实现您想要的最简单方法如下:
class HasId a where
getId :: a -> UUID
class HasId a => MyClass1 a where
method1 = -- NOTE: Use "getId" instead of plain "id".
当您定义数据类型时,您只需执行以下操作:
data Data1 = Data1
{ id :: UUID
, field2 :: String
, field3 :: Int
}
instance HasId Data1 where
getId = id
如果要向家庭添加新数据类型,只需创建HasId
类的新实例。
你不需要任何扩展,没有任何幻想,没有图书馆。当然你可能会缩短代码或做一些更有趣的事情,但我更喜欢使用简单的代码,这些代码可以运行,我理解的代码与我不理解的代码有关。