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

Ser*_*nin 4 haskell graph

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


如果我做

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
Run Code Online (Sandbox Code Playgroud)

我有一个预期的错误

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
Run Code Online (Sandbox Code Playgroud)

因为类型 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
Run Code Online (Sandbox Code Playgroud)

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

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

Joa*_*ner 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
Run Code Online (Sandbox Code Playgroud)

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

  • 这是GHC Prelude的设计者使用的方法.例如,我们有[]的两个`Monad`实例,其中一个可以通过将列表包装到`ZipList`来访问 (3认同)