5

我有兴趣推广一些计算工具以使用Cayley Table,这意味着基于查找表的乘法运算。

我可以创建一个最小的实现,如下所示:

date CayleyTable = CayleyTable {
    ct_name :: ByteString,
    ct_products :: V.Vector (V.Vector Int)
} deriving (Read, Show)

instance Eq (CayleyTable) where
 (==) a b = ct_name a == ct_name b

data CTElement = CTElement { 
    ct_cayleytable :: CayleyTable,
    ct_index   :: !Int
}

instance Eq (CTElement) where
 (==) a b = assert (ct_cayleytable a == ct_cayleytable b) $
            ct_index a == ct_index b

instance Show (CTElement) where
   show = ("CTElement" ++) . show . ctp_index

a **** b = assert (ct_cayleytable a == ct_cayleytable b) $
           ((ct_cayleytable a) ! a) ! b

然而,这种方法存在许多问题,首先是通过比较进行运行时类型检查,但包括无法正常工作ByteString的事实。read知道我应该如何正确地做到这一点吗?

我可以想象使用提供乘法并验证其类型一致性的类型类创建一系列 newtypes ,等等,除非在执行 IOCTElement1CTElement2IntCTElement

理想情况下,也可能有一些技巧可以只传递这个ct_cayleytable指针的一个副本,也许使用像 的隐式参数?cayleytable,但这不能很好地处理多个不兼容的 Cayley 表,并且通常令人讨厌。

另外,我已经收集到向量的索引可以被视为一个comonad。是否有任何好的comonad 实例用于vector 或任何可能有助于平滑这种类型检查的东西,即使最终在运行时进行检查?

4

1 回答 1

1

你需要意识到的是 Haskell 的类型检查器只检查类型。所以你的 CaleyTable 需要是一个类。

class CaleyGroup g where
caleyTable :: g -> CaleyTable
... -- Any operations you cannot implement soley by knowing the caley table

data CayleyTable = CayleyTable {
...
} deriving (Read, Show)

如果在编译时不知道 caleyTable,则必须使用 rank-2 类型。由于编译器需要强制 CaleyTable 存在的不变量,因此当您的代码使用它时。

manipWithCaleyTable :: Integral i => CaleyTable -> i -> (forall g. CaleyGroup g => g -> g) -> a

例如可以实现。它允许您在 CaleyTable 上执行组操作。它通过组合iCaleyTable创建一个传递给第三个参数的新类型来工作。

于 2012-05-23T15:20:28.023 回答