4

I am trying to understand how this factorial example works using the function fix :: (a -> a) -> a.

Example:

factabs :: (Num a, Eq a) => (a -> a) -> a -> a
factabs fact 0 = 1
factabs fact x = x * fact (x-1)

f :: (Num a, Eq a) => a -> a
f = fix factabs

I do not see why fix factabs has this type... fix expects a function of type a -> a, how can we apply it to a function of type (a -> a) -> a -> a (a function that takes two parameters)? I am totally confused...

Basically I was trying to figure out how to convert the function limit below to something that uses fix. Would appreciate any help.

limit f n
    | n == next       = n
    | otherwise       = limit f next
    where
      next = f n
duplode
  • 31,361
  • 7
  • 69
  • 130
akonsu
  • 26,172
  • 26
  • 106
  • 175

2 Answers2

3

fix expects a function of type a -> a, how can we apply it to a function of type (a -> a) -> a -> a (a function that takes two parameters)? I am totally confused...

That works because all Haskell functions take just one parameter. Even though we often think of this type...

(a -> a) -> a -> a

... as one of a function of two arguments, we can also read it like...

(a -> a) -> (a -> a)

... that is, one of a function that takes one argument (an a -> a function) and produces a function of one argument (of type a). Now if we take...

fix :: (b -> b) -> b

... we can see how factabs fits it by replacing b with (a -> a).

Basically I was trying to figure out how to convert the function limit below to something that uses fix.

All you need to do is, starting from the original definition, replacing any recursive calls of limit with an extra argument and passing this limit-with-an-extra-argument to fix (as you will see, the types will match with no further ado).

duplode
  • 31,361
  • 7
  • 69
  • 130
  • And in case you are wondering like me, yes `fix factabs` evaluates to `((a -> a) -> (a -> a)) ---->` **`(a -> a)`** indeed – mucaho Aug 02 '15 at 13:04
0

Just for the record, here is a version of limit function that I posted in my question that uses fix:

limit :: Eq a => (a -> a) -> a -> a
limit = fix (\g f x -> let x' = f x
                       in if x == x' then x else g f x')
akonsu
  • 26,172
  • 26
  • 106
  • 175