如何在不使用标准库的情况下定义List.flatten?

问题描述 投票:0回答:1

最初代码位于

List.flatten
(OCaml 标准库)中。但是,我不想使用标准库。因此我定义了
flatten
函数。
List.flatten
期间效果很好。在我实现 custom_flatten 后,它显示“错误:此模式与 'a * 'b 类型的值匹配,但需要一个与 int 类型的值匹配的模式”

我可以知道我的

custom_flatten
功能出了什么问题吗?

代码片段:

type move = Fill of int | Drain of int | Transfer of int * int;;


type state = {
  jar_volumes: int list;
  current_state: int list;
  moves: move list;
}

let rec reversed lst =
  let rec reverse acc = function
    | [] -> acc
    | head :: tail -> reverse (head :: acc) tail
  in
  reverse [] lst;;

let rec mapi_Two f index list =
  match list with
  | [] -> []
  | x :: xs ->
    let result = f index x in
    result :: mapi_Two f (index + 1) xs

(*Error after implement this*)
let custom_flatten lst =
  let rec aux acc = function
    | [] -> acc
    | [] :: xs -> aux acc xs
    | (h :: t) :: xs -> aux (h :: acc) (t :: xs)
  in
  reversed (aux [] lst)

let generate_transfers jar_idx jar_count =
  let transfer_indices =
    init jar_count (fun target_idx -> (jar_idx, target_idx))
  in
  filter (fun (source, target) -> source <> target) transfer_indices
  |> mapi_Two (fun (source, target) i -> Transfer (source, target))

(*The only flatten is in this function*)
let generate_possible_moves state =
  let jar_count = length state.jar_volumes in
  let generate_fills_and_drains jar_idx = [Fill jar_idx; Drain jar_idx] in
  let generate_transfers jar_idx = generate_transfers jar_idx jar_count in
  let moves_for_jar jar_idx =
    (generate_fills_and_drains jar_idx) @ (generate_transfers jar_idx)
  in
  custom_flatten (mapi_Two (fun i _ -> moves_for_jar i) 0 state.jar_volumes)

let perform_move state move =
  let new_state = doMove state.jar_volumes state.current_state move in
  { state with current_state = new_state; moves = move :: state.moves }

这个错误是我更改了

flatten
功能后才出现的。

Error: This pattern matches values of type 'a * 'b
       but a pattern was expected which matches values of type int

RichardHuxton 编辑:这是您的实际错误及其指向的内容:

File "stackoverflow_20231025.ml", line 38, characters 19-35:
38 |   |> mapi_Two (fun (source, target) i -> Transfer (source, target))
                        ^^^^^^^^^^^^^^^^
Error: This pattern matches values of type 'a * 'b
       but a pattern was expected which matches values of type int

那是我将

init jarcount ...
更改为
List.init jarcount
之后。

list ocaml flatten
1个回答
0
投票

所以(我是一个 ocaml 初学者,所以请仔细检查我的想法)你的

mapi_Two
定义如下:

let rec mapi_Two f index list =
...
    let result = f index x in
...

所以 - 它接受一个函数、索引和列表,并将索引作为第一个参数传递给该函数。我假设索引是

int

然后当你调用它时:

mapi_Two (fun (source, target) i -> Transfer (source, target))

您正在传递

mapi_Two
一个接受
(source, target)
(这是错误消息中的
a * b
)而不是 int 的函数。

© www.soinside.com 2019 - 2024. All rights reserved.