指定类的约束

时间:2015-06-10 12:00:31

标签: haskell typeclass

我在不同的模块中有三个数据声明:

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

2 个答案:

答案 0 :(得分:4)

  

所以MyClass1只能实例化Data1,Data2和Data3,因为它们都有字段ID?

那些你不知道的类型也有那个领域?

一般来说,你可以使用Lens完成类似的事情(常规的Haskell记录是IMHO不可用的);如果您为字段_Data1Id_Data2Id(可自定义)命名,则会为HasId提供idData1课程和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类的新实例。

你不需要任何扩展,没有任何幻想,没有图书馆。当然你可能会缩短代码或做一些更有趣的事情,但我更喜欢使用简单的代码,这些代码可以运行,我理解的代码与我不理解的代码有关。

相关问题