Python Decorators - not desirable in Haskell

Submitted by metaperl on Wed, 11/29/2006 - 2:08am.

This is not a planned out post, but I feel the need to compare Python decorators with The Haskell Way.

I recently read Philip J. Eby's article on decorators and it was eye-opening.
Let's see first what the purpose and definition of a Python decorator is before comparing them with The Haskell Way.

PURPOSE
Philip says that one use of decorators is to reduce code duplication. For example if a set of methods needs to be wrapped for additional functionality, such as synchronization, pre/post conditions, etc, then you can simply annotate each with the appropriate decorators.

The second use is to have the meta-information about functions right with the function so that the data is never out of sync with the function. Then you can locate all methods with certain characteristics via the decorator API (I suppose)

DEFINITION

I don't know why it took Phillip to the middle of the paper to define a decorator, but I think it was a good move... to sort of whet your appetite before giving you the definition. After all, this is not a mathematical proof. Anyway, a decorator is "...a callable object (like a function) that accepts one argument—the function being decorated. The return value of the decorator replaces the original function definition."

Comparison with Haskell
The very first thing that comes to mind is decorating destroys manifest interface. You can no longer examine a piece of code and examine the type signature of the functions it calls and know what is supposed to happen.

Haskell employs an entirely different approach to modifying function behavior. If you have a stereotyped way of modifying a set of functions, you would have to call the modifying function not call the original decorated function.

This is actually more flexible and composeable - the original function does one thing simply and clearly, then any combination of control strategies can be layered on top via other functions.

Let's take each of Philip's purported purposes of Python Decorators and see how Haskell accomplishes the same thing, but with that unmatched Haskell-esque elegance, flair, power and control. Yes, that's right, all 4 terms apply: elegance, flair, power and control:

CODE DUPLICATION
Well, that's what functions are for. If there is a list of things that need to be done to a function, then that itself is another function taking the first function as an argument.

The additional power of The Haskell Way is that you are not tied down to decorating a single function in a single way... for example: is it really the case that you should be decorating the division of two numbers with an exception? What happens when you want to decorate it with something to generate HTML instead?

SCATTTERING OF KNOWLEDGE
Phillip says that sometimes "...a framework needs to be able to locate all of a program's functions or methods that have a particular characteristic, such as 'all of the remote methods accessible to users with authorization X.'"

But I dont know about that. When was the last time I needed this sort of information? If so, is seat-of-the-pants annotation the way go? Why not use Template haskell to generate all such methods ahead of time?

CONCLUSION

Decorators do not belong in Haskell. They rob a language of referential transparency. They result in "pull-style" programming as opposed to injecting control.

Submitted by metaperl on Tue, 12/05/2006 - 6:14pm.

well, dons courteously donated some code showing t hat
decorators are just function composition

-- modify arguments, then apply f, yielding a decoreate f
f (x,y) = x + y
annotate x y = ((x * 2),(y * 3))
g = (f .) . annotate -- f (annotate a b))

-- modify result
f' (x,y) = x + y
annotate' z = z * 2
g = annotate . f -- = annotate (f (a,b))

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.