В OCaml все элементы списка должны быть одного типа.Таким образом, значение [1; [2; 3]; 4]
само по себе недопустимо.Он содержит два элемента типа int
и один элемент типа int list
.По сути, ваше изложение проблемы, которую нужно решить, невозможно.
$ ocaml312
Objective Caml version 3.12.0
# [1; [2; 3]; 4];;
Characters 4-10:
[1; [2; 3]; 4];;
^^^^^^
Error: This expression has type 'a list
but an expression was expected of type int
Это звучит как домашнее задание, поэтому я просто скажу, что ограничение себя списками, действительными в OCaml, может упростить задачу.решить.
Редактировать
ОК, теперь проблема может быть решена!
Суть сообщения об ошибке типа заключается в следующем.У вас есть накопленный результат acc
(типа int list
в примере).Вы хотите добавить в него список x
(также типа int list
).Вы разбили x
на head
(int
) и remainder
(int list
).Как видите, remainder
не подходит для вашей функции my_flat
.Он хочет int list list
, то есть список списков целых.Фактически, ваш рекурсивный вызов почти наверняка должен перейти к flatten
, а не к my_flat
.
Еще одна проблема, которую я вижу: аргументы List.fold_right
: функция, список и начальное значение,При тестовом вызове my_flat
последние два вы предоставляете в другом порядке.Пустой список []
- это ваше начальное значение.
Надеюсь, этого достаточно, чтобы вы начали.Поскольку вы только начинаете работать с OCaml, вероятно, перед его работой, вероятно, возникнет еще одна или две проблемы.
Edit 2
Вот еще пара комментариев, которые могутбудьте спойлерами, если вы все еще работаете над собственным решением ....
Более поздняя версия вашей функции my_flat
находится в стандартной библиотеке OCaml под именем List.flatten
.Интересно взглянуть на реализацию:
let rec flatten = function
[] -> []
| l::r -> l @ flatten r
Я бы назвал это очень элегантным решением, но, к сожалению, это не хвостовая рекурсия.Таким образом, он будет занимать некоторое (линейное) количество стекового пространства и может даже аварийно завершить работу для очень длинного списка.
Вот один из них, основанный на той же идее, с использованием стандартного трюка с аккумулятором FP для получения рекурсивного поведения хвоста (какзамечено Томасом):
let flatten2 ll =
let rec go acc = function
| [] -> List.rev acc
| l :: r -> go (List.rev_append l acc) r
in
go [] ll
Как это часто бывает, хвостовая рекурсивная версия накапливает результат в обратном порядке и инвертирует его в конце.