数独网格的 Haskell 可变数组

Haskell mutable array for sudoku grid

提问人:Ralph 提问时间:3/18/2018 更新时间:3/18/2018 访问量:136

问:

我正在尝试在 Haskell 中编写一个数独生成器/求解器作为学习练习,但我在 monad 中生成可变数组时遇到了困难。ST

我的函数的输入将是 81 个字符,其中包含数字 through 和占位符 (, , 或 )。parseString19.-0

这是我写的函数,但它不会编译,我无法弄清楚我需要什么类型:

import           Control.Monad
import           Control.Monad.ST
import           Data.Array.ST
import qualified Data.Array.Unboxed as U
import           Data.Char          (digitToInt, isDigit)
import           Data.List          (zip)

data Cell = Cell
  { values   :: Word16
  , original :: Bool
  } deriving (Show)

parse input =
  runSTUArray $
  U.array ((0, 0), (8, 8)) $
  map
    (\(i, d) ->
       ( (quot i 9, mod i 9)
       , if isDigit d && d /= '0'
           then Cell {values = bit $ digitToInt d, original = True}
           else Cell {values = 2 ^ 11 - 2, original = False})) $
  zip [0 ..] input

该函数的输出应该是包含单元格的可变 9 x 9 网格的不可变表示形式。

我该如何解决这个问题?

哈斯克尔 单子 可变

评论

1赞 Thomas M. DuBuisson 3/18/2018
拥有可变事物的不可变表示意味着什么?您要求帮助修复的“这个”是什么?
0赞 Fried Brice 3/18/2018
您确定需要一个可变的 9 x 9 网格吗?

答:

1赞 HTNW 3/18/2018 #1

您正在使用 ,这意味着打算有一个 .你不能有这个:仅适用于选定的少数元素类型。您可以使用普通的 .或者,你可以拥有并把它塞进去。无论如何,没有理由使用 .该函数将执行:runSTUArrayUArray (Int, Int) CellUArrayArraytype Cell = Word16BoolSTlistArray

import Data.Array
-- listArray :: Ix i => (i, i) -> [e] -> Array i e

parse :: String -> Array (Int, Int) Cell
parse = listArray ((0, 0), (8, 8)) . map chr2cell
  where chr2cell c | isDigit c && c /= '0' = Cell (bit $ intToDigit c) True
                   | otherwise = Cell (2^11 - 2) False

如果您选择使用 ,您只需要稍作修改即可。如果您最近参加 GHC,您甚至可以选择:UArray _ Word16chr2cell

{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
type Cell = Word16
pattern Cell :: Word16 -> Bool -> Word16
pattern Cell { values, original } <- (_ -> (values, original))
  where Cell values original = _

您可以在其中使用分别解构和构造 A 和 A 的单元格的函数填充第一个和第二个 S,以创建一个记录模式同义词,该同义词的工作方式与普通记录构造函数类似,但实际上不会创建新类型。_Word16Bool

评论

0赞 Ralph 3/18/2018
谢谢。这是非常有帮助的。