我正在 Haskell 中编写一个数独生成器/求解器作为学习练习。
My solve
函数接受一个UArray
但返回一个State Int (UArray ...)
这样它也可以返回解决问题时发现的最大难度级别。
到目前为止,这是我的功能(仍处于实验性的早期阶段):
import Control.Monad.State (State, put)
import Control.Monad.Trans.Class (lift)
import Data.Array.MArray (thaw)
import Data.Array.ST (runSTUArray)
import Data.Array.Unboxed (UArray)
-- ...
type Cell = Word16
solve :: UArray (Int, Int) Cell -> State Int (UArray (Int, Int) Cell)
solve grid = do
return $ runSTUArray $ do
arr <- thaw grid
lift $ put 42
return arr
它实际上还没有对可变数组做任何事情。我只是想让它进行类型检查put 42
,但目前出现以下错误:
• Couldn't match kind ‘*’ with ‘* -> *’
When matching the kind of ‘ST’
• In a stmt of a 'do' block: lift $ put 42
In the second argument of ‘($)’, namely
‘do arr <- thaw grid
lift $ put 42
return arr’
In the second argument of ‘($)’, namely
‘runSTUArray
$ do arr <- thaw grid
lift $ put 42
return arr’
|
128 | lift $ put 42
| ^^^^^^^^^^^^^
runSTUArray ...
是一个纯值,它对“外部单子”一无所知。和State
关心你如何使用它,你不能不透明地将它传递给ST。
你可以做什么:
Option1:更改整个程序,将更多逻辑移至 ST 端。您可以使用 STRef 而不是 State:
solve :: ST s (STRef Int) -> ST s (UArray (Int, Int) Cell) -> ST s ()
...
Option2:手动提取并传递给ST,然后返回并显式放置。但有一个复杂的情况。runSTUArray
不允许将另一个值与数组一起获取。我不知道如何使用当前的数组函数安全地完成它。不安全的话你可以更好地重新实施runSTUArray
它可以传递另一个值。您还可以添加假单元并在那里编码新状态。
导出另一个值的方式在向量包中存在,有(新版本中)createT
函数不能采用裸向量,而是可以采用包含它的结构(甚至多个向量)。因此,总的来说,您的示例如下:
import Control.Monad.State (State, put, get)
import Data.Word (Word16)
import qualified Data.Vector.Unboxed as DVU
type Cell = Word16
solve :: DVU.Vector Cell -> State Int (DVU.Vector Cell)
solve grid = do
oldState <- get
let (newState, newGrid) = DVU.createT (do
arr <- DVU.thaw grid
pure (oldState + 42, arr))
put newState
pure newGrid
不幸的是,向量只是一维的
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)