Functional programming 如何使用两个模板参数编写一个类,其中一个是另一个的列表/数组?

Functional programming 如何使用两个模板参数编写一个类,其中一个是另一个的列表/数组?,functional-programming,clean-language,Functional Programming,Clean Language,我想用Clean(一种非常类似于Haskell的语言)解决这个问题: 有一个类节点t,它有两个实例:实例节点边列表和实例节点邻接。我想创建一个图,它是一个数组或节点列表 图形的定义是: class Graph t1 t2 | Node t2 where resetGraph :: (t1 t2) -> (t1 t2) graphSize :: (t1 t2) -> Int ... 我想写实例。一个带数组,一个带列表。首先,我尝试使用list,但得到一个

我想用Clean(一种非常类似于Haskell的语言)解决这个问题:

有一个
类节点t
,它有两个实例:
实例节点边列表
实例节点邻接
。我想创建一个图,它是一个数组或节点列表

图形的定义是:

class Graph t1 t2 | Node t2 where
    resetGraph  :: (t1 t2) -> (t1 t2)
    graphSize   :: (t1 t2) -> Int
    ...
我想写实例。一个带数组,一个带列表。首先,我尝试使用list,但得到一个错误:
t2未定义

instance Graph [t1] t2 | t2 t1 where
    (resetGraph) :: [t1] -> [t1]
    (resetGraph) x = []
    ...
例如,可以这样调用它:
resetGraph listAdj
,其中listAdj是
邻接
节点的列表


如果我只写:
实例图[tt]tt
,那么我会得到这个错误:
错误:这个类型变量在一个实例类型中出现不止一次

class Graph l t | Node t where
    resetGraph :: (l t) -> l t
你给的是
l
种类
*->*
。种类是对类型的抽象。大致上,kind
*
表示您有一个“完整”类型。例如,
Int
[Char]
a->String
都是同类的
*
。当类型仍然“需要参数”时,它的种类为
*->*
。例如,如果您有
::可能a=只是一个|无
,那么
可能Int
属于
*
类型,但简单地说
可能
属于
*->*
类型,因为它仍然需要一个参数。因此,当编写
resetGraph::(lt)->lt
时,编译器认识到
t
l
的一个参数,因此给出
resetGraph
种类
*
的唯一方法是给出
l
种类
*
(和
t
种类
*

您需要知道的第二件事是,
[Char]
(Int,Int)
a->Real
等类型也可以写入前缀:
[]Char
(,)Int Int
(>)Real
。您可以将
[]
进行比较:它仍然需要一个参数(此处为
Char
)才能成为完整的类型。因此,类型
[]
具有种类
*->*
。类似地,
(,)
也有种类
*->*->*
,因为它仍然需要两种类型才能完成,
(>)
。(注:本手册第4.5节对此进行了记录)

结合这两者,你应该写:

instance Graph [] Adjacency where
    ...
然后,
resetGraph
的类型被解析为
([]邻接)->[]邻接
,这与
[邻接]->[邻接]
相同

对于数组,前缀表示法是
{}Adjacency
表示
{Adjacency}

顺便说一下:类似的操作在
StdEnv
中通过类
length
完成:

// StdOverloaded.dcl
class length m :: !(m a) -> Int

// StdList.icl
instance length [] where ...

谢谢,我现在更明白了。由于某种原因,我在
实例图[]节点上得到一个错误,其中…
。错误是:
节点未定义
。节点由两个实例定义。我在
类图t1 t2 |节点t2没有发现错误,在那里
@IterAtor欢迎您。很抱歉,我写了
节点
,我应该在那里写
邻接
边列表
。(错误告诉您,
Node
不是一个类型。)它现在已被修复。但我认为我不应该直接使用
Adjacency
EdgeList
,因为我在
Graph
中需要的每个函数都是在
Node
中定义的(在两个实例中都定义了这些函数)@IterAtor在这种情况下,您可以使用
类图l where resetGraph::(l t)->l t | Node t
,即将
节点
依赖项移动到类成员(因为它不限制类变量)。@迭代器或者,定义
类图l where resetGraph::l->l
,并用
实例图[a]|节点a
实例化,取决于您是要在
图形
类中还是仅在该实例中强制执行
节点
上下文。