What does fixIO do?

前端 未结 2 780
后悔当初
后悔当初 2021-02-13 02:09

The System.IO docs contains a mysterious, undocumented function fixIO. Its source only adds to the mystery:

fixIO :: (a -> IO a) -> IO a
fixIO         


        
相关标签:
2条回答
  • 2021-02-13 02:29

    fixIO is the IO equivalent of fix.

    You've probably seen this definition of the fibonacci sequence:

    fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
    

    which reuses the fibs variable within the definition of fibs to do corecursion. It works because we exploit laziness to define each element of fibs before it needs to be used.

    We can use fix to do the same without having to define a variable, tying the knot for us:

    fix $ \fibs -> 1 : 1 : zipWith (+) fibs (tail fibs)
    

    Which is handy if you don't especially need to keep the entire fibonacci sequence, you just want to know its tenth element:

    λ (fix $ \fibs -> 1 : 1 : zipWith (+) fibs (tail fibs)) !! 9
    55
    

    fixIO is similar, except it lets you recurse on the output of an IO action. That's why you got your "thread blocked" error - you were using the corecursive result without defining it.

    λ fmap (take 10) . fixIO $ \fibs -> putStrLn "computing fibs" >> return (1 : 1 : zipWith (+) fibs (tail fibs))
    computing fibs
    [1,1,2,3,5,8,13,21,34,55]
    
    0 讨论(0)
  • 2021-02-13 02:43

    fixIO is the witness to the MonadFix IO instance. See the HaskellWiki page on MonadFix and the paper A Recursive do for Haskell.

    0 讨论(0)
提交回复
热议问题