Сообщение об ошибке SML / NJ не делает это ужасно ясным.Если вы поместите этот код в REPL Moscow ML и включите функцию contains
, которую вы использовали, но не определили, вы получите следующую ошибку:
! Toplevel input:
! List.hd(List.nth(l, i)) := 1
! ^
! Type clash: expression of type
! int list list
! cannot have type
! 'a ref list list
Ваша программа дает сбой, потому что вы обрабатываете int значений, как если бы они были int ref .
В функциональном программировании вы обычно стараетесь избегать изменяемых переменных ( ref значения).
Чтобы уточнить проблему, с которой вы столкнулись:
List.hd(List.nth(l, i)) := 1
означает «Установить ссылку, возвращаемую List.hd(List.nth(l, i))
в 1
. Так как l
является списком int , то List.nth(l, i)
возвращает i
-й элемент этого (или аварийного завершения), который является int списком Затем List.hd(...)
принимает 1-й элемент этого (или аварийно завершает работу), который является int . Не int ref .
Чтобы эта строка работала,вам понадобится l : int ref list list
.
Но вы этого не хотите.
i = i - 1
- это логическое выражение, которое возвращает true
, если i
эквивалентно мнеСебе минус 1. Это не так для любого int .Вы, вероятно, намереваетесь вычесть 1 из i
и поместить результат в i
, но вы не можете, потому что i
не является изменяемой переменной, и вызывается оператор для обновления ref :=
.
Если ваша проблема заключалась в преобразовании списка
val m = [ [ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ] ]
в список
val n = [ [ 1, 2, 3 ],
[ 1, 5, 6 ],
[ 1, 8, 9 ] ]
, тогда aкороткий способ сделать это - использовать List.map
:
val n = List.map (fn row => 1 :: List.drop (row, 1)) m
Более ручной способ, который практикует рекурсию и сопоставление с шаблоном по итерации как while ... do
(это работает только при наличии изменяемых переменных) и частичные функции , такие как List.hd
и List.nth
(может произойти сбой):
fun f [] = []
| f (row::m) = (1 :: List.drop (row, 1)) :: f m
val n = f m
Если вам нужна изменяемая версия, рассмотрите модуль Array2
вместо списка int list .
Вот одно решение Array2
, в котором курсор увеличиваетсяиспользуя рекурсию:
fun appulate f from to =
if from > to then ()
else (f from; appulate f (from+1) to)
fun f col m =
appulate (fn row => Array2.update (m, row, col, 1))
0 (Array2.nRows m - 1)
fun show m =
Array2.appi Array2.RowMajor (fn (_, col, c) =>
print (Int.toString c ^ (if col + 1 = Array2.nCols arr then "\n" else "" )))
{base=arr,row=0,col=0,nrows=NONE,ncols=NONE};
val m' = Array2.fromList m
val n' = f 0 m'
val _ = show n'
Я понимаю, что я не приводил примеров while ... do
или какой-либо коллекции int ref s, которыеh работает с ref
, !
и :=
.