如何在Haskell中创建具有不同行为的相同类型?

时间:2013-09-04 12:29:41

标签: haskell graph

我使用Haskell和Functional Graph Library来表示图形。有两种比较图形的方法,直接比较函数相等,或者比另一个函数,我写道, isIsomorph 。 我想使用hash map来收集图表。为此,我必须为我的图形创建类 Eq 的实例。但是我需要两个哈希映射,第一个用于按函数等于进行比较的图形,第二个用于由函数进行比较的图形isIsomorph


如果我这样做

type Fragment = Gr Atom Bond {-- Gr is a type constructor from the Functional Graph Library}

    instance Eq (Gr Atom Bond) where    
        g == g1 = equal g g1

    instance Eq Fragment where  
        g == g1 = isIsomorph g g1

我有一个预期的错误

Duplicate instance declarations:
      instance [overlap ok] Eq (Gr Atom Bond) -- Defined at HLab.hs:45:10
      instance [overlap ok] Eq Fragment -- Defined at HLab.hs:48:10

由于 type decalration只是换行。

我可以用另一种方式

data Fragment = Fragment {fgraph :: Gr Atom Bond}

instance Eq (Gr Atom Bond) where    
    g == g1 = equal g g1

instance Eq Fragment where  
    Fragment g ==  Fragment g1 = isIsomorph g g1

这是正确的,但我使用了“重型”构造函数 data ,这种方式也很不方便,我必须通过附加函数fgraph从片段中获取图形。

在代码的各个部分划分这些类型是否有“美丽”和“真实”的方法?

1 个答案:

答案 0 :(得分:11)

在代码的各个部分划分这种类型的“美丽”和“真实”方式?是使用newtype而不是data:对于所有类型系统的目的,它们是不同的(特别是,您可以定义不同的类型类实例),但它们共享相同的运行时表示,并且与data无关:

newtype Fragment = Fragment {fgraph :: Gr Atom Bond}

instance Eq (Gr Atom Bond) where    
    g == g1 = equal g g1

instance Eq Fragment where  
    Fragment g == Fragment g1 = isIsomorph g g1

当尝试在片段上使用图形函数时,您仍然需要在图形和片段之间进行转换。