我遇到了这个非常古老的数独代码,这对我来说似乎很有意思,主要是这种丑陋的类型
type T = (Int,Int) -> [Int]
要理解这个功能,例如
mark :: ((Int,Int),Int) -> T -> T
mark (p@(i,j),n) s q@(x,y) =
if p==q then [n] else
if x==i || y==j || e x i && e y j then delete n $ s q else s q
where e a b = div (a-1) 3==div (b-1) 3
我可以用实际类型替换T
mark :: ((Int,Int),Int) -> (Int,Int)->[Int] -> (Int,Int)->[Int]
mark (p@(i,j),n) s q@(x,y) =
现在类型参数似乎没有正确排列。 p匹配完美,但我对" s"感到困惑。如果我跳到标记的呼叫它就像这样.....这里的列表我可以很容易地看到它的键值对的数组,如(1,2)等键。这些已经在sudoku中过滤空白或零。
input :: String -> (Int,Int) -> [Int]
input s = foldr mark (const [1..9]) $
[(p,n) | (p,n) <- zip idx $ map read $ lines s >>= words, n>0]
使用此列表和累加器调用标记函数,该函数是一个函数(const [1..9])。这不符合类型签名。
mark :: ((Int,Int),Int) -> (Int,Int)->[Int] -> (Int,Int)->[Int]
代码问题在于我无法看到标记功能的实际结果,我仍然不了解。当它传递给第三个函数时,它会获得一些输出。关于如何理解这个sphagetti代码的任何解释?
答案 0 :(得分:4)
此类型的值
type T = (Int,Int) -> [Int]
将任何数独单元格(x,y) :: (Int,Int)
的坐标映射到单元格可能具有的一组可能值(表示为数字列表[Int]
)。
函数const [0..9]
将任何单元格映射到所有数字的集合中。它充当数独求解器的初始状态:在开始时,假设任何单元格可能有任何数字。