I would like to solve this problem in Clean (a language very similar to Haskell):
There is a class Node t, with two instances: instance Node EdgeList and instance Node Adjacency. I would like to create a Graph, which is an array or list of Nodes.
The definition of the Graph is:
class Graph t1 t2 | Node t2 where
resetGraph :: (t1 t2) -> (t1 t2)
graphSize :: (t1 t2) -> Int
...
I would like to write the instances. One with array, and one with list. First, I tried with list, but I get an error: t2 not defined
instance Graph [t1] t2 | t2 t1 where
(resetGraph) :: [t1] -> [t1]
(resetGraph) x = []
...
It will be called for example like this: resetGraph listAdj where listAdj is a list of Adjacency Nodes
If I just write: instance Graph [tt] tt then I get this error: Error: this type variable occurs more than once in an instance type.
The first thing to understand here is that when you write
you give
lkind*->*. Kinds are an abstraction from types. Roughly, kind*means you have a 'complete' type. For example,Int,[Char],a -> Stringare all of kind*. When a type still 'needs an argument', it has kind*->*. For example, if you have:: Maybe a = Just a | Nothing, thenMaybe Intis of kind*, but simplyMaybeis of kind*->*because it still needs one argument. So, when writingresetGraph :: (l t) -> l t, the compiler recognises thattis an argument tol, so the only way to giveresetGraphkind*(which is necessary for a function), is to givelkind*->*(andtkind*).The second thing you need to know is that types as
[Char],(Int,Int)anda -> Realkan all be written prefix as well:[] Char,(,) Int Int,(->) a Real. You can compare[]toMaybe: it still needs one argument (hereChar) to be a complete type. Hence, the type[]has kind*->*. Similarly,(,)has kind*->*->*, because it still needs two types to be complete, as does(->). (Note: this is documented in section 4.5 of the language report).Combining these two, you should write:
Then, the type of
resetGraphis resolved to([] Adjacency) -> [] Adjacencywhich is the same as[Adjacency] -> [Adjacency].For arrays, the prefix notation is
{} Adjacencyfor{Adjacency}.By the way: something similar to this is done in
StdEnvwith the classlength: