我有兴趣将一些计算工具概括为使用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
正常工作的事实。知道我该怎么做才能正确吗?
我可以想象为CTElement1
创建一个新类型CTElement2
,Int
等系列,其中CTElement
类型类提供乘法并验证其类型一致性,但做IO时。
理想情况下,也可能有一些技巧只传递此ct_cayleytable
指针的一个副本,可能使用隐式参数,如?cayleytable
,但这不适用于多个不兼容的Cayley表并且通常令人讨厌。
另外,我已经收集到一个向量的索引可以被视为一个comonad。是否有任何好的comonad实例用于向量或其他任何可能有助于平滑这种类型检查的实例,即使最终在运行时执行它?
答案 0 :(得分: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上执行组操作。它通过组合i
和CaleyTable
来创建一个新类型,然后传递给它的第三个参数。