1

Hello everyone I'm trying to implement the higher-order function fix, which computes an attractive fixed point of an arbitrary function f :: a -> a from an initial point x. That is, a fixed point of the form fᴷ(x) for a given f and x.

-- CONTRACT
fix :: Eq a => (a -> a) -> a -> a
-- DEFINITION [TODO: Implement fix]
fix f x  = ?

My current attempt is:

fix f x | f x == x = x
        | otherwise = fix f x
    where x = f x

Note: Your function will not terminate if the function does not converge from the starting point. can someone help me please ? I tried but it didn't return anything

duplode
  • 31,361
  • 7
  • 69
  • 130
Alaa Alsayed
  • 119
  • 7

3 Answers3

7

A common misconception is that when you write x = ..., you assign a value in Haskell. In Haskell one does not assign a value, one declares one.

This thus means that basically you constructed a variable x in the where clause that is not the x in the head of the function, so something like:

fix :: Eq a => (a -> a) -> a -> a
fix f _ | f x == x = x
        | otherwise = fix f x
    where x = f x

Here you thus defined x in terms of itself: x = f x, so that means if Haskell aims to evaluate that, it will start calculating f(f(f(f(f(f(...)))))), but without any checks if the fixed point has been reached.

The solution is thus to introduce a new variable, for example x2, and thus use this like:

fix :: Eq a => (a -> a) -> a -> a
fix f x | x == x2 = x
        | otherwise = fix f x2
    where x2 = f x

So here x2 is the next x. Given x == x2, we return x (or x2), if not, we calculate the fixed point of f and x2, so we advanced one step in the "Quest for the fixed point".

Willem Van Onsem
  • 321,217
  • 26
  • 295
  • 405
  • it doesn't work either returns an wrong answer or it returns nothing :\\ Ihave typed fix (*2)3 it should return 12 but it returns nothing . – Alaa Alsayed Dec 02 '18 at 19:15
  • 1
    @Amerov: why is the fixed point of `(*2)` `3`? The idea of a fixed point is `f x == x`, but `(*2) 12 == 24`, not `12`. – Willem Van Onsem Dec 02 '18 at 19:16
  • 1
    @Amerov the fixed point of (*2) is 0, and it's not attractive, so it won't be reached for any argument that's not 0 to begin with. – Will Ness Dec 02 '18 at 19:40
  • @WillNess can you give me an example please just to know how to use it or how it works – Alaa Alsayed Dec 02 '18 at 19:46
  • 2
    @Amerov `fix (*2) 0` would work. or e.g. ``fix (`div` 2) 100``. Or `let collatz x | even x = div x 2 | x <= 1 = 1 | otherwise = (3*x+1)` and then `fix collatz 99`. – Will Ness Dec 02 '18 at 19:51
  • @WillNess does it work on String if the argument is a string – Alaa Alsayed Dec 02 '18 at 20:13
  • 1
    @Amerov yes, why not? `String` is an instance of `Eq` alright. You just need to devise a function of String to String which has an (attractive) fixed point. – Will Ness Dec 02 '18 at 20:21
  • 1
    `fix reverse ""` does work. `""` is a non-attractive fixed point of reverse. also, `fix reverse "12321"` works. – Will Ness Dec 02 '18 at 20:29
  • 3
    try `fix cos 1` to find the Dottie number. – karakfa Dec 02 '18 at 20:52
4

Give a different name to the next step of iteration, like this:

where x' = f x

(instead of where x = f x). Now review the rest of your existing code, and for each occurrence of x, ask yourself: did I mean x here, or x'?

Daniel Wagner
  • 128,625
  • 9
  • 198
  • 347
4

You already have answers on how to writefix from scratch. If you'd like to try it using some standard Haskell functions, I suggest you look at the function until.

until :: (a -> Bool) -> (a -> a) -> a -> a

Note the type of until is rather similar to the one you want. It just takes one extra argument of the form a -> Bool. The expression until p f x iteratively applies f starting with the initial point x, until some condition p is satisfied. And you should easily be able to write fix in the form,

fix = until p 

for some function p :: a -> Bool. Now you just need to implement this stopping condition p, which checks if a point y you've calculated is a fixed point of f, that is if f y == y.

Jorge Adriano
  • 2,280
  • 11
  • 21