[英]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.