我有一个f :: [a] -> b对无限列表进行操作的函数(例如take 5,takeWhile (< 100) . scanl (+) 0等等)。我想为这个函数提供由严格的单子动作(例如randomIO)生成的值。
从这个问题中,我了解到repeatandsequence技巧方法不适用于严格的单子,如下例所示:
import Control.Monad.Identity
take 5 <$> sequence (repeat $ return 1) :: Identity [Int]
-- returns `Identity [1,1,1,1,1]`
-- works because Identity is non-strict
take 5 <$> sequence (repeat $ return 1) :: IO [Int]
-- returns `*** Exception: stack overflow`
-- does not work because IO is strict
Run Code Online (Sandbox Code Playgroud)
因此,我考虑在单子上下文“内部”使用该函数。我受到这个循环编程示例的启发并尝试:
let loop …Run Code Online (Sandbox Code Playgroud)