【问题标题】:Haskell mutable array for sudoku grid数独网格的 Haskell 可变数组
【发布时间】:2018-03-17 21:53:46
【问题描述】:

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

parse 函数的输入将是一个包含 81 个字符的 String,其中包含数字 19 和占位符(.-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 网格的不可变表示。

我该如何解决这个问题?

【问题讨论】:

  • 拥有可变事物的不可变表示是什么意思?您寻求帮助修复的“这个”是什么?
  • 您确定需要一个可变的 9 x 9 网格吗?

标签: haskell monads mutable


【解决方案1】:

您正在使用runSTUArray,这意味着有UArray (Int, Int) Cell 的意图。你不能这样:UArray 仅适用于少数几个元素类型。您可以使用普通的Array。或者,您可以拥有type Cell = Word16,然后将Bool 塞入其中。无论如何,没有理由使用STlistArray 函数可以:

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

如果您选择使用UArray _ Word16,您只需稍微修改chr2cell。如果您最近使用 GHC,您甚至可以选择:

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

您可以在第一个和第二个_s 中分别使用分别从Word16Word16Bool 解构和构造单元格的函数来创建一个像普通记录一样工作的记录模式同义词构造函数,但实际上并不创建新类型。

【讨论】:

  • 谢谢。这很有帮助。
猜你喜欢
  • 2011-11-05
  • 1970-01-01
  • 2013-11-10
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多