簡體   English   中英

遞歸地運行一個 State monadic action

[英]run a single State monadic action recursively

我有一個名為step單子操作,我想遞歸運行它,直到它返回Nothing值。 下面的代碼有效,但我在每一步都調用runState 我正在尋找的解決方案將在 state monad 中建立,然后在最后調用runState一次。

我知道我在這里使用Maybe尖叫“變壓器”,但我試圖讓它在沒有變壓器的情況下工作。

testFn :: Int -> Maybe Int
testFn i = if i > 5 then Nothing else Just i

step :: State Int (Maybe Int)
step = do
    i <- get
    let i' = testFn i
    put $ maybe i (1 +) i'
    return i'

go :: Int -> Int -> Maybe Int
go s a = case runState step s of 
    (Nothing, _)  -> Just a
    (Just a', s') -> go s' a'

回復:

> go 0 0
Just 5

您可以編寫一個修飾符,將 a a -> State s (Maybe a)轉換為a -> State sa

repeatM :: Monad m => (a -> m (Maybe a)) -> a -> m a
repeatM f = g
    where g x = f x >>= maybe (pure x) g

因此,我們可以創建一個函數:

repeatStep :: Int -> State Int Int
repeatStep = repeatM (const step)

然后go只是:

go :: Int -> Int -> (Int, Int)
go s a = runState (repeatStep a) s

這里 2 元組的第一項是Int ,它是輸出Nothing之前的最后一個Just …輸出。 2-tuple 的第二項是這種情況下的狀態。

然后我們的go返回:

Prelude Control.Monad.State> go 0 0
(5,6)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM