Sharing vs. non-sharing fixed-point combinator

前端 未结 3 439
庸人自扰
庸人自扰 2020-12-31 22:07

This is the usual definition of the fixed-point combinator in Haskell:

fix :: (a -> a) -> a
fix f = let x = f x in x

On https://wiki.

3条回答
  •  说谎
    说谎 (楼主)
    2020-12-31 22:48

    _Y is translated to the following STG:

    _Y f = let x = _Y f in f x
    

    fix is translated identically to the Haskell source:

    fix f = let x = f x in x
    

    So fix f sets up a recursive thunk x and returns it, while _Y is a recursive function, and importantly it’s not tail-recursive. Forcing _Y f enters f, passing a new call to _Y f as an argument, so each recursive call sets up a new thunk; forcing the x returned by fix f enters f, passing x itself as an argument, so each recursive call is into the same thunk—this is what’s meant by “sharing”.

    The sharing version usually has better memory usage, and also lets the GHC RTS detect some kinds of infinite loop. When a thunk is forced, before evaluation starts, it’s replaced with a “black hole”; if at any point during evaluation of a thunk a black hole is reached from the same thread, then we know we have an infinite loop and can throw an exception (which you may have seen displayed as Exception: <>).

提交回复
热议问题