Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make same types with different behavior in Haskell?

Tags:

graph

haskell

I use Haskell and Functional Graph Library to represents graphs. There are two ways to compare graphs, directly, over function equal, or over another function, i wrote, isIsomorph. I want to use hash map to collect graphs. To do so I have to create instance of class Eq for my graphs. But I need two hash maps, first for graphs that compared by function equal, and second for graphs that compated by function isIsomorph.


If I do

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

I have got an expected error

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

Because of type decalration is only wrap.

I can use another way

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

That is correct but I have used an "heavy" type constructor data, this way is also inconvenient, I have to got graphs from fragments by addtional function fgraph.

Is there any "beautiful" and "true" way to divide this types in various parts of code?

like image 344
Sergey Sosnin Avatar asked Dec 21 '22 00:12

Sergey Sosnin


1 Answers

The "beautiful" and "true" way to divide this types in various parts of code? is to use newtype instead of data: For all type system purposes, they are different (in particular, you can define different type class instances), but they share the same run-time representation and there is no additional like with 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

You will still need to convert between graphs and fragments when trying to use graph functions on fragments.

like image 165
Joachim Breitner Avatar answered Mar 05 '23 12:03

Joachim Breitner