I am trying to build my own simple graph library that I can use for advent of code. I have a type class Graph and one concrete implementation MapGraph that uses Data.Map
class Graph g where
nodeSet :: (Ord n) => g -> S.Set n
data MapGraph e n = MapGraph {mGraph :: M.Map n [(e,n)]} deriving Show
instance (Ord e,Ord n) => Graph (MapGraph e n) where
nodeSet mapGraph = S.fromList $ M.keys $ mGraph mapGraph
The nodeSet function works correctly if I have it as a standalone function outside of the instance declaration
testNodeSet mapGraph = S.fromList $ M.keys $ mGraph mapGraph
*Main> testNodeSet $ mapGraphFromEdgeList $ parseEdgeList connectionList
fromList ["B","C","D","E","F","G","H","I","J","K","L","S"]
But I get a compile error from it inside of the instance
Main.hs:59:22: error:
• Couldn't match type ‘n1’ with ‘n’
‘n1’ is a rigid type variable bound by
the type signature for:
nodeSet :: forall n1. Ord n1 => MapGraph e n -> S.Set n1
at Main.hs:59:3-9
‘n’ is a rigid type variable bound by
the instance declaration
at Main.hs:58:10-46
Expected type: S.Set n1
Actual type: S.Set n
• In the expression: S.fromList $ M.keys $ mGraph mapGraph
In an equation for ‘nodeSet’:
nodeSet mapGraph = S.fromList $ M.keys $ mGraph mapGraph
In the instance declaration for ‘Graph (MapGraph e n)’
• Relevant bindings include
mapGraph :: MapGraph e n (bound at Main.hs:59:11)
nodeSet :: MapGraph e n -> S.Set n1 (bound at Main.hs:59:3)
|
59 | nodeSet mapGraph = S.fromList $ M.keys $ mGraph mapGraph
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I have no idea what the error message is trying to tell me except that I have something wrong with type signatures. The type of tetsNodeSet looks correct to me
testNodeSet :: Ord a => MapGraph e a -> S.Set a
What do I need to do to fix my issue? I did wonder if I need to add (Ord e,Ord n) => to my declaration of the data type MapGraph but I couldn't work out how to put it there without getting a compile error