如何在haskell中分解复杂类型的别名?

时间:2015-03-20 15:54:44

标签: haskell sudoku

我遇到了这个非常古老的数独代码,这对我来说似乎很有意思,主要是这种丑陋的类型

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代码的任何解释?

1 个答案:

答案 0 :(得分:4)

此类型的值

type T = (Int,Int) -> [Int]

将任何数独单元格(x,y) :: (Int,Int)的坐标映射到单元格可能具有的一组可能值(表示为数字列表[Int])。

函数const [0..9]将任何单元格映射到所有数字的集合中。它充当数独求解器的初始状态:在开始时,假设任何单元格可能有任何数字。