advantages of using fix to define rcursive functions

Hi, I read about the usage of "fix" to define recursive functions. Although I think that I understood how to use "fix", I still wonder what the advantages of "fix" are (as compared to the "conventional" approach to define recursive functions). Any hints are appreciated. Thanks Harald. " Ce courriel et les documents qui y sont attaches peuvent contenir des informations confidentielles. Si vous n'etes pas le destinataire escompte, merci d'en informer l'expediteur immediatement et de detruire ce courriel ainsi que tous les documents attaches de votre systeme informatique. Toute divulgation, distribution ou copie du present courriel et des documents attaches sans autorisation prealable de son emetteur est interdite." " This e-mail and any attached documents may contain confidential or proprietary information. If you are not the intended recipient, please advise the sender immediately and delete this e-mail and all attached documents from your computer system. Any unauthorised disclosure, distribution or copying hereof is prohibited."

harald.rotter:
Hi,
I read about the usage of "fix" to define recursive functions. Although I think that I understood how to use "fix", I still wonder what the advantages of "fix" are (as compared to the "conventional" approach to define recursive functions).
Any hints are appreciated.
There's no obvious advantage that I know of, other than being cute. An example from xmonad: allocaXEvent $ \p -> fix $ \again -> do more <- checkMaskEvent d enterWindowMask p when more again So actually, I suppose it is useful for small, anonymous recursive definitions. -- Don

Donald Bruce Stewart wrote:
harald.rotter:
Hi,
I read about the usage of "fix" to define recursive functions. Although I think that I understood how to use "fix", I still wonder what the advantages of "fix" are (as compared to the "conventional" approach to define recursive functions).
Any hints are appreciated.
So actually, I suppose it is useful for small, anonymous recursive definitions.
It also exposes the recursive computation structure for direct manipulation, enabling one to perform certain program transformations/refactorings. Search for "fixpoint fusion" and "fixed point promotion". While one might say: that's the business of a compiler, actually existing ones are not very sophisticated in that regard, so one might want to do such transformations "by hand"... Ciao, Janis. -- Dr. Janis Voigtlaender http://wwwtcs.inf.tu-dresden.de/~voigt/ mailto:voigt@tcs.inf.tu-dresden.de

voigt:
Donald Bruce Stewart wrote:
harald.rotter:
Hi,
I read about the usage of "fix" to define recursive functions. Although I think that I understood how to use "fix", I still wonder what the advantages of "fix" are (as compared to the "conventional" approach to define recursive functions).
Any hints are appreciated.
So actually, I suppose it is useful for small, anonymous recursive definitions.
It also exposes the recursive computation structure for direct manipulation, enabling one to perform certain program transformations/refactorings. Search for "fixpoint fusion" and "fixed point promotion". While one might say: that's the business of a compiler, actually existing ones are not very sophisticated in that regard, so one might want to do such transformations "by hand"...
Oh, excellent point. Just as naming particular loop structures (such as 'map' or 'unfoldr') enable more precise optimisations, such as fusion, so naming recursive functions saves the compiler some work discovering the name. -- Don

Harald ROTTER
I read about the usage of "fix" to define recursive functions. Although I think that I understood how to use "fix", I still wonder what the advantages of "fix" are (as compared to the "conventional" approach to define recursive functions).
You might enjoy this paper: Bruce J. McAdam, 1997. That about wraps it up: Using FIX to handle errors without exceptions, and other programming tricks. Tech. Rep. ECS-LFCS-97-375, Laboratory for Foundations of Computer Science, Department of Computer Science, University of Edinburgh. http://www.lfcs.informatics.ed.ac.uk/reports/97/ECS-LFCS-97-375/ -- Edit this signature at http://www.digitas.harvard.edu/cgi-bin/ken/sig It is the first responsibility of every citizen to question authority. Benjamin Franklin

Just casting my vote for the helpfulness of this reference.
Trying to summarize in one phrase: you can do interesting
manipulations to functions before applying fix that you cannot do to
functions after applying fix (conventional functions fall in this
second category).
On 7/26/07, Chung-chieh Shan
You might enjoy this paper:
Bruce J. McAdam, 1997. That about wraps it up: Using FIX to handle errors without exceptions, and other programming tricks. Tech. Rep. ECS-LFCS-97-375, Laboratory for Foundations of Computer Science, Department of Computer Science, University of Edinburgh. http://www.lfcs.informatics.ed.ac.uk/reports/97/ECS-LFCS-97-375/
-- Edit this signature at http://www.digitas.harvard.edu/cgi-bin/ken/sig It is the first responsibility of every citizen to question authority. Benjamin Franklin
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On 7/26/07, Nicolas Frisby
Trying to summarize in one phrase: you can do interesting manipulations to functions before applying fix that you cannot do to functions after applying fix (conventional functions fall in this second category).
Something similar holds for types where we can use something like data Fix s a = In{out :: s a (Fix s a)} to construct fixed points of functors, as opposed to functions. Any recursive type can be expressed using Fix, so the question is, why would you do it? Well, associated to every recursive type is a corresponding fold and unfold, of which the familiar foldr and unfoldr are special cases for the List type. If we define our types using Fix of some functor, then we can also have fold and unfold built for us automatically from the functor, alongside the actual type. There are a number of papers that discuss this, including "The Essence of the Iterator Pattern" by Jeremy Gibbons and Bruno C. d. S. Oliveira. -- Dan

Another advantage here - an analog I'm always eager to point out - is
that just as we can augment functions if they haven't yet been fixed,
we can augment functors. One can extend datatypes and functions (a la
open functions) or generically generate constructs such as (co-)free
(co-)monads in this way.
On 7/26/07, Dan Piponi
On 7/26/07, Nicolas Frisby
wrote: Trying to summarize in one phrase: you can do interesting manipulations to functions before applying fix that you cannot do to functions after applying fix (conventional functions fall in this second category).
Something similar holds for types where we can use something like
data Fix s a = In{out :: s a (Fix s a)}
to construct fixed points of functors, as opposed to functions. Any recursive type can be expressed using Fix, so the question is, why would you do it? Well, associated to every recursive type is a corresponding fold and unfold, of which the familiar foldr and unfoldr are special cases for the List type. If we define our types using Fix of some functor, then we can also have fold and unfold built for us automatically from the functor, alongside the actual type.
There are a number of papers that discuss this, including "The Essence of the Iterator Pattern" by Jeremy Gibbons and Bruno C. d. S. Oliveira. -- Dan _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Thursday 26 July 2007, Harald ROTTER wrote:
Hi,
I read about the usage of "fix" to define recursive functions. Although I think that I understood how to use "fix", I still wonder what the advantages of "fix" are (as compared to the "conventional" approach to define recursive functions).
As others have said, it allows you to define anonymous recursive functions (not necessarily small!). FPers have traditionally advocated using lots of small, named, top-level functions, but I think it's amazing how much more readable code becomes when some of those single-use functions are inlined. You can't inline a recursive function, but you can inline an application of fix. Jonathan Cast http://sourceforge.net/projects/fid-core http://sourceforge.net/projects/fid-emacs

On Thursday 26 July 2007, Harald ROTTER wrote:
Hi,
I read about the usage of "fix" to define recursive functions. Although I think that I understood how to use "fix", I still wonder what the advantages of "fix" are (as compared to the "conventional" approach to define recursive functions).
Any hints are appreciated.
It may not be using fix per-se, but one interesting thing you can do with a fixed-point combinator is write one that memoizes the produced function:
table bounds f = array bounds [(i, f i) | i <- range bounds]
dp bounds f = (memo!) where memo = table bounds (f (memo!))
Then you can write something like:
fib' _ 1 = 1 fib' _ 2 = 1 fib' me n = me (n - 1) + me (n - 2) fib = dp (1, 30) fib'
And fib will only ever compute the nth fibonacci number once, saving it thereafter. Of course, with arrays, this only works over a fixed range, but you can write structures that will allow you to memoize over arbitrary domains this way (either lazy lists of exponentially sized arrays, or infinite, lazy tries will get you O(lg n) lookup on integers, for example; and the latter should be able to memoize over strings, among other things). The advantage being, you can write a library that will automatically do dynamic programming for you, instead of having to write the same knot-tying array/map code every time. So, that's not an example of why fix is directly useful, but it's certainly useful to understand how to use it for this reason. -- Dan
participants (8)
-
Chung-chieh Shan
-
Dan Doel
-
Dan Piponi
-
dons@cse.unsw.edu.au
-
Harald ROTTER
-
Janis Voigtlaender
-
Jonathan Cast
-
Nicolas Frisby