Прежде всего, вы должны действительно научиться использовать сопоставление с образцом и использовать его вместо операторов List.hd
и List.tl
. Также плохая идея передавать кортежи в функции вместо передачи нескольких аргументов.
Например, функция addLists
, которую вы определяете как
let rec addLists = function (alist, blist) ->
if((alist == []) && (blist == []))
then []
else List.hd alist +. List.hd blist::addLists(List.tl alist, List.tl blist)
, в то время как идиоматический код OCaml будет выглядеть как
let rec add_lists xs ys = match xs,ys with
| [],[] -> []
| x::xs, y::ys -> x +. y :: add_lists xs ys
| _,[] | [],_ -> invalid_arg "add_listss: lists are of different lengths"
Обратите внимание также, какФункция сопоставления ошибок автоматически показывает, что ваши списки могут иметь различную длину.
Теперь функция hopTrain
. Это обычная ошибка в программировании OCaml, интерпретировать сообщение об ошибке очень локально и делать поспешные выводы :) Если вы посмотрите более внимательно, сообщение об ошибке соответствовало всему выражению opTrain3(hopTrainAllStates(allStates), hopTrainAllStates(allStates))
(и оно было выделено для вас OCaml).
Таким образом, в основном говорится, что это выражение в порядке, и оно имеет тип float list list list
, то есть трехмерный список. Но мне нужно float list list
здесь, чтобы твой куб не вписывался в мой квадрат.
Следующий вопрос, который вы должны задать себе, - почему компилятор ожидает квадрат здесь? Ответ прост - это ваша ветка then
, которая является выражением hopTrainAstate(List.hd allStates)
типа float list list
. Итак, у вас есть выражение
if cond then it_is_square else it_is_cube
Но обе стороны выражения if
должны иметь один и тот же тип - так как тип выражения не может зависеть от какого-либо условия - это статическое свойство значения.
Я действительно не знаю, что ваша функция должна вычислять, если есть только одно состояние, но следующий код, по крайней мере, проверяет:
let rec hopTrain = function (allStates) ->
if((allStates == []))
then[]
else if((List.tl allStates == []))
then [hopTrainAstate(List.hd allStates)] (* if only one state then output that state *)
else hopTrain3(hopTrainAllStates(allStates), hopTrainAllStates(allStates));;
Кроме того, возможно, это правилаигра вашего задания, так что вы должны использовать это 'a list list list
для структурирования ваших данных. Но в реальном мире это считается очень плохой практикой. Вы всегда должны использовать определенные типы данных для обозначения объектов в вашем домене, например, что-то вроде этого
type row = {row : float list}
type matrix = { rows : row list}
type weights = { weights : matrix}
Эта жесткая типизация сделает ваш код легче для понимания и труднее для взлома. Помните следующее высказывание бампера OCaml:
Если сомневаетесь, используйте больше типов!