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
l
kind*->*
. Kinds are an abstraction from types. Roughly, kind*
means you have a 'complete' type. For example,Int
,[Char]
,a -> String
are all of kind*
. When a type still 'needs an argument', it has kind*->*
. For example, if you have:: Maybe a = Just a | Nothing
, thenMaybe Int
is of kind*
, but simplyMaybe
is of kind*->*
because it still needs one argument. So, when writingresetGraph :: (l t) -> l t
, the compiler recognises thatt
is an argument tol
, so the only way to giveresetGraph
kind*
(which is necessary for a function), is to givel
kind*->*
(andt
kind*
).The second thing you need to know is that types as
[Char]
,(Int,Int)
anda -> Real
kan 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
resetGraph
is resolved to([] Adjacency) -> [] Adjacency
which is the same as[Adjacency] -> [Adjacency]
.For arrays, the prefix notation is
{} Adjacency
for{Adjacency}
.By the way: something similar to this is done in
StdEnv
with the classlength
: