二维矩阵 sml 插入列表 - 简单代码

2d matrix sml inserting to list - simple code

我有一个 sml-nj 项目,我想在其中使用具有 "Squares" 的 'list of lists' 结构。我正在尝试以递归方式将值插入到列表列表中,但我仍然不明白如何将元素插入到二维列表中。 注意 - 我不能使用 'REF',只能使用 http://smlfamily.org/Basis/list.html#SIG:LIST.app:VAL 这些功能。

datatype SquareContent = Mine | Digit of int | Blank;
datatype Square = Revealed of SquareContent | Concealed of SquareContent;
fun createMineSweeperGrid (n:int)
:(Square list   list)= 
let
fun createMines (rowCounter:int, colCounter:int
, retGame:Square list list):(Square list list) = 
if rowCounter=n then   
retGame         (* finished all rows, should be n lists of size n*)
else
if colCounter=n then   (*finished current row, move on*)
createMines (rowCounter+1, 0, mines,retGame)
else   

let
val squareToInsert = Concealed(Mine)  (* I wish to insert 'squareToInsert'         
to retGame[rowCounter][colCounter], it's done dynamically, but I don't know 
how to do that *)
in
createMines (rowCounter, colCounter+1, retGame) 
end

in
createMines (0,0,[])
end

我可以插入任何类型的 Square,它是动态决定的,这里我只给出了隐藏的 Mine 的例子,所以你可以帮助我.. HELP..?

要认识到的重要一点是,在标准 ML 中,您不会改变现有结构;相反,你创造新的。 (标准 ML 支持 可变结构,通过 ref 和它的朋友,但这不是一件容易做的事情,我看到你已经 - 正确地 - 排除了它.)

因此,一般来说,在链表的中间插入一些东西是非常昂贵的:它需要 "unwinding" 链表到你想插入的地方,然后插入值,最后构建一个你解开的所有东西的副本。例如,这里有一个函数会在列表的索引 i 处插入一个值 x

fun insert (x, 0, L) = x :: L
  | insert (x, i, h :: t) = h :: insert (x, i - 1, t)
  | insert (_, _, nil) = raise Subscript

幸运的是,您编写的函数无需在 already-built 链表的中间插入任何内容;相反,如果我正确理解它要做什么,它总是将新方块放在 first 列表的 beginning 处。所以:

let
  val squareToInsert = Concealed(Mine)
  val topRow :: rest = retGame
in
  createMines (rowCounter, colCounter+1, (squareToInsert::topRow)::rest) 
end

请注意,您还需要修复另一个错误,即您实际上从未创建新行:您对 "finished current row, move on" 发表了评论,但随后它的处理过程与之前完全相同仍在同一行(只是重置数字,就好像它已移动到新行一样)。要解决此问题,请在要在顶部添加新行时使用 [] :: retGame,并使用 [[]] 而不是初始板的 [](以便它以空行开始).