询问OCaml中的返回类型、列表和集合数据结构

询问OCaml中的返回类型、列表和集合数据结构,ocaml,Ocaml,我有一个函数将列表计算为布尔矩阵,其中num\u of_name:'a list->'a->int:返回元素在列表中的位置 1) 我想要mat\u of_dep\u rel:'a list->bool数组。 我的问题是,从第一个列表开始,iter应该是一个列表l,而不是一个空列表[]。但是如果我返回l而不是[],它将给我一个类型:('a*'a list)list->boolean数组。这不是我想要的 我想知道如何返回mat\u of_dep\u rel:'a list->bool array数组

我有一个函数将列表计算为布尔矩阵,其中
num\u of_name:'a list->'a->int
:返回元素在列表中的位置

1) 我想要
mat\u of_dep\u rel:'a list->bool数组。

我的问题是,从第一个
列表开始,iter
应该是一个列表
l
,而不是一个空列表
[]
。但是如果我返回
l
而不是
[]
,它将给我一个类型:
('a*'a list)list->boolean数组。
这不是我想要的

我想知道如何返回
mat\u of_dep\u rel:'a list->bool array数组?

let mat_of_dep_rel l =
  let n = List.length l in
  let m = Array.make_matrix n n false in
  List.iter (fun (s, ss) ->
    let i = num_of_name ss s in
    List.iter (fun t ->
      m.(i).( num_of_name ss t) <- true) ss) [];
  m;;
另一个函数eq_类通过收集所有等价类来计算一组等价类。我更喜欢使用列表数据结构,而不是使用集合。但就目前而言,我并不真正理解这里的代码

你能给我解释一下吗?如果我想使用列表数据结构,如何使用它?OCaml中的列表和集合数据结构有什么不同?智能交通系统的先进性/劣势

let eq_classes m =
  IntSet.fold (fun i l -> IntMap.add i (eq_class m i) l)
    IntSet.empty IntMap.empty;;
3) 我的最后一个问题是。在拥有所有等价类之后,我想对它们进行排序。我还有其他功能

let cmp m i j = if eq_class m i = eq_class m j then 0
  else if m.(i).(j) then -1 else 1;;

let eq_classes_sort m l = List.sort (cmp m) l;;
对于最后一个函数,我希望它为我返回b
ool数组->int list list
not
bool数组->int list->int list


谢谢你的帮助。

你的问题有很多地方是错误的或模糊的,但我会尽量回答

问题1 显然,您正在尝试将依赖关系图的表示形式从列表转换为矩阵。将依赖关系图表示为一个列表(实际上,从任意列表中构建布尔矩阵没有什么有趣的方法),这没有任何意义,因此您可能打算使用一个成对的
(int*int)列表,每对
(i,j)
都是一个依赖关系
i->j

如果您有一个任意对的
('a*'a)列表
,您可以使用
num\u of_name
函数轻松地对元素进行编号,将其转换为上述
(int*int)列表

一旦有了这些,就可以轻松构建矩阵:

let matrix_of_dependencies dependencies =
  let n = List.fold_left (fun (i,j) acc -> max i (max j acc)) 0 dependencies in  
  let matrix = Array.make_matrix (n+1) (n+1) false in
  List.iter (fun (i,j) -> matrix.(i).(j) <- true) dependencies ;
  matrix

val matrix_of_dependencies : (int * int) list -> bool array array
我只检查
I->j
,因为如果依赖关系确实是一种等价关系(自反、传递、对称),那么
I->j
意味着
j->I
。如果您的依赖关系不是等价关系,那么您实际上是在关系的图表示中寻找循环,这与您建议的算法完全不同,除非您首先计算依赖关系图的传递闭包

集合和列表都是有良好文档记录的标准模块,它们的文档可以在线免费获取。如果您对StackOverflow有具体问题,请询问他们

您要求我们解释您为
eq\u类
提供的代码。解释是它在一个空集上折叠,所以它返回它的初始值——一个空映射。因此,这是完全没有意义的。更合适的实施方式是:

let equivalence_classes matrix = 
  let classes = ref [] in 
  Array.iteri begin fun element _ ->
    if not (List.exists (List.mem element) !classes) then
      classes := equivalence_class matrix element :: !classes 
  end matrix ;
  !classes

val equivalence_classes : bool array array -> int list list
这将以列表的形式返回所有等价类(每个等价类都是一个单独的列表)

问题3 类型系统指出您已经定义了一个在
int
上工作的比较函数,因此您只能使用它对
int列表进行排序。如果要对
int list
(等价类列表)进行排序,则需要为
int list
元素定义一个比较函数

假设(如上所述)依赖关系图是传递闭合的,您所要做的就是使用现有的比较算法并将其应用于每个类的任意表示形式:

let compare_classes matrix c c` = 
  match c, c` with 
    | h :: _, h' :: _ -> if matrix.(h).(h') then 1 else -1
    | _ -> 0 

let sort_equivalence_classes matrix = List.sort (compare_classes matrix)

此代码假定为1。每个等价类只出现一次,1。每个等价类至少包含一个元素。当使用等价类时,这两种假设都是合理的,并且预先消除重复类和空类是一个简单的过程

你的问题有很多错误或模糊之处,但我会尽量回答

问题1 显然,您正在尝试将依赖关系图的表示形式从列表转换为矩阵。将依赖关系图表示为一个列表(实际上,从任意列表中构建布尔矩阵没有什么有趣的方法),这没有任何意义,因此您可能打算使用一个成对的
(int*int)列表,每对
(i,j)
都是一个依赖关系
i->j

如果您有一个任意对的
('a*'a)列表
,您可以使用
num\u of_name
函数轻松地对元素进行编号,将其转换为上述
(int*int)列表

一旦有了这些,就可以轻松构建矩阵:

let matrix_of_dependencies dependencies =
  let n = List.fold_left (fun (i,j) acc -> max i (max j acc)) 0 dependencies in  
  let matrix = Array.make_matrix (n+1) (n+1) false in
  List.iter (fun (i,j) -> matrix.(i).(j) <- true) dependencies ;
  matrix

val matrix_of_dependencies : (int * int) list -> bool array array
我只检查
I->j
,因为如果依赖关系确实是一种等价关系(自反、传递、对称),那么
I->j
意味着
j->I
。如果您的依赖关系不是等价关系,那么您实际上是在关系的图表示中寻找循环,这与您建议的算法完全不同,除非您首先计算依赖关系图的传递闭包

集合和列表都是有良好文档记录的标准模块,它们的文档可以在线免费获取。如果您对StackOverflow有具体问题,请询问他们

您要求我们解释您为
eq\u类
提供的代码。解释是它在一个空集上折叠,所以它返回它的初始值——一个空映射。因此,它是完整的
let compare_classes matrix c c` = 
  match c, c` with 
    | h :: _, h' :: _ -> if matrix.(h).(h') then 1 else -1
    | _ -> 0 

let sort_equivalence_classes matrix = List.sort (compare_classes matrix)