如何分解 haskell 中的复杂类型别名?
How to break up complex type aliases in haskell?
我遇到了这个非常古老的数独代码,它对我来说似乎是希腊语,因为主要是这种丑陋的类型
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) 等。这些已经在数独中被过滤为空白或零。
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 代码的任何解释?
这种类型的值
type T = (Int,Int) -> [Int]
将任何数独单元格的坐标 (x,y) :: (Int,Int)
映射到此类单元格可能具有的一组可能值(表示为数字列表 [Int]
)。
函数const [0..9]
将任何单元格映射到所有数字的集合中。它充当数独求解器的初始状态:开始时,假设任何单元格可能有任何数字。
我遇到了这个非常古老的数独代码,它对我来说似乎是希腊语,因为主要是这种丑陋的类型
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) 等。这些已经在数独中被过滤为空白或零。
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 代码的任何解释?
这种类型的值
type T = (Int,Int) -> [Int]
将任何数独单元格的坐标 (x,y) :: (Int,Int)
映射到此类单元格可能具有的一组可能值(表示为数字列表 [Int]
)。
函数const [0..9]
将任何单元格映射到所有数字的集合中。它充当数独求解器的初始状态:开始时,假设任何单元格可能有任何数字。