Fixed point combinator in Haskell

前端 未结 5 1509
[愿得一人]
[愿得一人] 2020-12-16 16:31

The fixed point combinator doesn\'t always produce the right answer given the definition:

fix f = f (fix f)

The following code does not ter

5条回答
  •  爱一瞬间的悲伤
    2020-12-16 16:48

    I'm not entirely qualified to talk about what the "fixpoint combinator" is, or what the "least fixed point" is, but it is possible to use a fix-esque technique to approximate certain functions.

    Translating Scala by Example section 4.4 to Haskell:

    sqrt' :: Double -> Double
    sqrt' x = sqrtIter 1.0
      where sqrtIter guess | isGoodEnough guess = guess
                           | otherwise          = sqrtIter (improve guess)
            improve guess = (guess + x / guess) / 2
            isGoodEnough guess = abs (guess * guess - x) < 0.001
    

    This function works by repeatedly "improving" a guess until we determine that it is "good enough". This pattern can be abstracted:

    myFix :: (a -> a)       -- "improve" the guess
          -> (a -> Bool)    -- determine if a guess is "good enough"
          -> a              -- starting guess
          -> a
    fixApprox improve isGoodEnough startGuess = iter startGuess
      where iter guess | isGoodEnough guess = guess
                       | otherwise          = iter (improve guess)
    
    sqrt'' :: Double -> Double
    sqrt'' x = myFix improve isGoodEnough 1.0
      where improve guess = (guess + x / guess) / 2
            isGoodEnough guess = abs (guess * guess - x) < 0.001
    

    See also Scala by Example section 5.3. fixApprox can be used to approximate the fixed point of the improve function passed into it. It repeatedly invokes improve on the input until the output isGoodEnough.

    In fact, you can use myFix not only for approximations, but for exact answers as well.

    primeAfter :: Int -> Int
    primeAfter n = myFix improve isPrime (succ n)
      where improve = succ
            isPrime x = null [z | z <- [2..pred x], x `rem` z == 0]
    

    This is a pretty dumb way to generate primes, but it illustrates the point. Hm...now I wonder...does something like myFix already exist? Stop...Hoogle time!

    Hoogling (a -> a) -> (a -> Bool) -> a -> a, the very first hit is until.

    until p f yields the result of applying f until p holds.

    Well there you have it. As it turns out, myFix = flip until.

提交回复
热议问题