Тип списка с плавающим списком выражений, но ожидался тип списка с плавающим списком, но подписи верны? - PullRequest
0 голосов
/ 30 октября 2019

Я исправил все, не волнуйтесь

1 Ответ

2 голосов
/ 30 октября 2019

Прежде всего, вы должны действительно научиться использовать сопоставление с образцом и использовать его вместо операторов 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:

Если сомневаетесь, используйте больше типов!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...