SMLNJ:运营商和;操作数don';t同意[tycon mismtach]-进行列表分配
我在SMLNJ中编写了以下函数:SMLNJ:运营商和;操作数don';t同意[tycon mismtach]-进行列表分配,sml,smlnj,Sml,Smlnj,我在SMLNJ中编写了以下函数: fun f(id : int, l : int list list) = let val i : int = length(l) - 1 in while i > 0 do ( if (exists(id, List.nth(l, i))) then List.hd(List.nth(l, i)) := 1 else(); i = i - 1 ) end; 收到
fun f(id : int, l : int list list) =
let
val i : int = length(l) - 1
in
while i > 0 do
(
if (exists(id, List.nth(l, i))) then
List.hd(List.nth(l, i)) := 1
else();
i = i - 1
)
end;
收到的错误如下:
Error operator and operand don't agree [tycon mismatch]
operator domain: 'Z ref * 'Z
operand: int * [int ty]
in expression:
List.hd (List.nth (l,i)) := 1
我知道运算符域是函数所期望的,而操作数是所提供的。
我认为这是因为int
不能分配给列表
类型。但是,我不清楚List.hdList.nth(l,I))
将如何导致int
以外的任何结果
请告知我如何修复此错误以及支持逻辑。SML/NJ的错误消息并没有非常清楚地说明这一点。如果将此代码放在REPL中,并包含已使用但未定义的函数
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
是一个int列表,那么l
返回该(或崩溃)元素的List.nth(l,i)
th元素,这是一个int列表。然后i
取其中的第一个元素(或崩溃),它是int,而不是int ref 要使这一行正常工作,您需要List.hd(…)
但你不想这样l:int-ref-list-list
是一个布尔表达式,如果i=i-1
等于其自身减去1,则返回i
。这对于任何整数都不是真的。您可能打算从true
中减去1,并将结果放入i
,但您不能,因为i
不是可变变量,并且是upd的运算符将ref命名为i
:=
如果您的问题是转换列表
val m = [ [ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ] ]
列入名单
val n = [ [ 1, 2, 3 ],
[ 1, 5, 6 ],
[ 1, 8, 9 ] ]
那么一个简单的方法就是使用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
如果你想要一个可变的版本,考虑模块而不是int列表。 下面是一个
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
,或任何使用ref
、!
和操作的int-ref集合的示例:=