Переместить список [1,2,3] в [3,1,2] в OCaml - PullRequest
0 голосов
/ 06 мая 2020

Я пытаюсь написать простую программу OCaml для продвижения вектора, то есть [1,2,3] переходит в [3,1,2] и так далее:

open Printf

let advance_list list =
    match list with 
    |[]   -> []
    |h::t -> t::h

let () = List.iter (printf "%d ") (advance_list [1;2;3])

но Я получаю

File "rotate_vector.ml", line 13, characters 16-17:
13 |     |h::t -> t::h
                     ^
Error: This expression has type 'a but an expression was expected of type
         'a list list
       The type variable 'a occurs inside 'a list list

Я не понимаю ошибку. Для меня я возвращаю первый элемент, добавленный к началу h, который является списком без первого элемента, который равен t

Ответы [ 2 ]

2 голосов
/ 06 мая 2020

Начало и конец списка не одного и того же типа. Для списка типа t list заголовок списка имеет тип t, а конец списка имеет тип t list. Другими словами, конец списка также является списком.

Итак, вы не можете использовать оператор :: для их переключения. Вам нужно что-то типа t слева и что-то типа t list справа.

В любом случае вам нужно разделить список в конце, а не в начале. Для этого вам понадобится что-то посложнее. Я мог бы представить себе функцию, которая просматривает список, отслеживая то, что она видела до сих пор (начало списка), а затем объединяет результат, когда он дойдет до конца.

0 голосов
/ 23 мая 2020
let get_last_elt l = 
 let list_rev = List.rev l in
  match list_rev with 
  [] -> failwith "The list is empty"
  |h::t -> let end_of_list = h in end_of_list

let delete_last_elt l = 
 let list_rev = List.rev l in
  match list_rev with 
  [] -> failwith "The list is empty"
  |h::t -> List.rev t

let advance_list l = 
 let end_of_list = get_last_elt l in
  match l with
  [] -> failwith "The list is empty"
  |h::t -> [end_of_list]@(delete_last_elt l)

Надеюсь, это поможет!

...