我遇到了这段代码,但我不知道 grid <- get
的作用是什么?做?我们怎么知道这个网格就是我们当前的网格呢?我们不会将其作为参数传递。那么我们如何使用它来抓取行呢?
data Grid = Grid [Row]
type GridState a = State Grid a
initializeGrid :: GridState ()
initializeGrid = do
setPositionToColor 2 0 Alive
setPositionToColor :: Int -> Int -> CellState -> GridState ()
setPositionToColor x y color = do
grid <- get
let rows = getRows grid
...
put newState
getRows :: Grid -> [Row]
...
最佳答案
State
monad 有效地隐藏了这样一个事实:每个函数都将状态值作为输入,并在输出中包含(可能已更改的)状态。 get
实际上只是返回隐藏的参数。
如果您在编写函数时不使用 State
,结果会更清晰。
-- State Grid a == Grid -> (Grid, a)
setPositionToColor :: Int -> Int -> Color -> Grid -> (Grid, ())
^^^^^^^^^^^^^^^^^^
当您调用setPositionToColor 2 0 Alive
时,您实际上并没有为网格的任何特定元素着色,因为还没有涉及网格。您只需返回一个函数,当使用 Grid
调用it时,将生成新修改的Grid
。
如果没有 Monad
实例,每次调用 setPositionToColor
都需要该附加参数,并且它将返回一个新的 Grid
传递给下一个电话。你的代码看起来像
let (grid1,_) = setPositionToColor x1 y1 color1 initialGrid
(grid2,_) = setPositionToColor x2 y2 color2 grid1
(grid3,_) = setPositionToColor x3 y3 color3 grid2
(grid4,_) = setPositionToColor x4 y4 color4 grid3
in grid4
<小时/>
Monad 实例所做的一切就是负责将中间的 Grid 值从一个函数传递到下一个函数;您需要做的就是提供 initialGrid
作为 runState
的参数,它实际上启动对组合 State
操作的调用。
-- Back to setPositionToColor :: Int -> Int -> Color -> State Grid a
let allFour = setPositionToColor x1 y1 color1 >>= (\() ->
setPositionToColor x2 y2 color2 >>= (\() ->
setPositionToColor x3 y3 color3 >>= (\() ->
setPositionToColor x3 y3 color4)))
in runState allFour initialGrid
或者,因为我们实际上并不关心每次调用返回的 ()
值,
let allFour = setPositionToColor x1 y1 color1 >>
setPositionToColor x2 y2 color2 >>
setPositionToColor x3 y3 color3 >>
setPositionToColor x3 y3 color4
in runState allFour initialGrid
使用do
表示法,
let allFour = do
setPosition x1 y1 color1
setPosition x2 y2 color2
setPosition x3 y3 color3
setPosition x4 y4 color4
in runState allFour initialGrid
关于Haskell var <- get 是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47930334/