What does fixIO do?

前端 未结 2 785
后悔当初
后悔当初 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]
    

提交回复
热议问题