Function OCaml和创建列表列表

Function OCaml和创建列表列表,function,logic,ocaml,Function,Logic,Ocaml,我目前正在尝试使用函数创建: 0 V12 V13 V14 V21 0 V23 V24 V31 V32 0 V34 V41 V42 V43 0 我发现的一种方法是使用这些方程: (2*V1 - 1)*(2*V2-1) = for spot V(1,2) in the Matrix (2*V1 - 1)*(2*V3-1) = for spot V(1,3) in the Matrix etc 到目前为止,我已经: let singleState state = if state = 0.

我目前正在尝试使用函数创建:

0  V12 V13 V14
V21 0  V23 V24
V31 V32 0  V34
V41 V42 V43 0
我发现的一种方法是使用这些方程:

(2*V1 - 1)*(2*V2-1) = for spot V(1,2) in the Matrix
(2*V1 - 1)*(2*V3-1) = for spot V(1,3) in the Matrix
etc
到目前为止,我已经:

let singleState state = 
if state = 0.0 then 0.0
else
    ((2.0 *. state) -. 1.0);;


let rec matrixState v = 
match v with
| [] -> []
| hd :: [] -> v
| hd :: (nx :: _ as tl) ->
    singleState hd *. singleState nx :: matrixState tl;;
我的结果是:

float list = [-3.; -3.; -3.; -1.]
当它们应该是一个列表时,如下所示:

0 -1 1 -1
-1 0 -1 1
1 -1 0 -1
-1 1 -1 0 
所以,它不是在列清单,而是在列一个清单。我也不知道如何使对角线为0

签名应如下所示:

val singleState : float list -> float list list = <fun>
val matrixState : float list list -> float list list = <fun>
我越来越

val singleState : float -> float = <fun>
val matrixState : float list -> float list = <fun>

有什么想法吗?

通过一些修正,您的函数将生成一行结果。然后你可以为你需要的每一行调用它一次。重复调用的一个好方法可能是使用List.map

假设这主要是一个学习练习,那么最好先制作一个如下矩阵:

V11 V12 V13 V14
V21 V22 V23 V24
V31 V32 V33 V34
V41 V42 V43 V44
我认为这将更容易计算

然后可以将对角线替换为零。下面是一些可以替代对角线的代码:

let replnth r n l =
    List.mapi (fun i x -> if i = n then r else x) l

let zerorow row (n, res) =
    (n - 1, replnth 0.0 n row :: res)

let zerodiag m =
    let (_, res) = List.fold_right zerorow m (List.length m - 1, []) in
    res

我更愿意为你的工作准备一个阵列

一个很好的函数是Array.init,它的工作原理是这样的

# Array.init 5 (fun x -> x);;  
- : int array = [|0; 1; 2; 3; 4|]  
let built_matrix = 
 let open Array in 
   init 4 (fun row -> 
     init 4 (fun col -> 
       if col=row then 0
       else vect.(row)+vect.(col)))
我们注意到5起到了数组大小的作用

但是,当你想要一个矩阵时,我们需要构建一个数组数组,它是通过两次调用Array.init实现的,最后一次调用嵌套在第一次调用中

# Array.init 3 (fun row -> Array.init 3 (fun col -> row+col));;
- : int array array = [|[|0; 1; 2|]; [|1; 2; 3|]; [|2; 3; 4|]|]
注意,我调用了变量row和col来表示它们对应于矩阵的行索引和列索引

最后,由于您的公式使用参考V保持值[|V1;V2;V3;V4 |]的向量,我们需要创建一个并将对它的调用合并到我们的矩阵生成器中,数组选项卡的单元格n上保持值的访问方式与tab.n-1类似

这最终引导我们找到了工作示例

let vect = [|1;2;3;4|] 

let built_matrix = 
  Array.init 4 (fun row -> 
    Array.init 4 (fun col -> 
      if col=row then 0
      else vect.(row)+vect.(col)))
当然,为了根据您的需求匹配这段代码,您必须根据自己的方便对其进行调整

关于语法的旁注, 使用OCaml的一些好特性可以避免每次重复数组。 我们可以像这样在本地打开一个模块

# Array.init 5 (fun x -> x);;  
- : int array = [|0; 1; 2; 3; 4|]  
let built_matrix = 
 let open Array in 
   init 4 (fun row -> 
     init 4 (fun col -> 
       if col=row then 0
       else vect.(row)+vect.(col)))
更简短的是,让开放数组进入。。。可以写为数组…,下面是一段在优秀的utop下解释的代码来说明它,我将利用这个机会将我们的矩阵转换为列表

utop # 
Array.(
  to_list 
  @@ map to_list 
  @@ init 4 (fun r -> 
     init 4 (fun c -> 
       if r = c then 0 
       else vect.(r)+ vect.(c))))
;;
- : int list list = [[0; 3; 4; 5]; [3; 0; 5; 6]; [4; 5; 0; 7]; [5; 6; 7; 0]]   

我希望它有帮助

啊,是的,这是一个练习,但它说不要使用列表。如果这是一个练习,我不想为您编写代码:-您可以使用显式递归打开这些函数。您也可以编写自己版本的列表函数。您使用的语言是“OCaml”,带有大写字母O和大写字母C。