# Function decorators

Decorator syntax refers to the desugaring of

``````@g(...)
def f(...):
...``````

into

``````def f(...):
...
f = g(...)(f)``````

`f` is called the “decorated” function, and `g` is called the “decorator.”

Here we look at several examples using decorators in Python, compare them to similar situations in Haskell, and discuss how lambdas let us achieve the same result without having a special syntax for decorators.

## Uses of decorators

We broadly categorize decorators into two kinds of uses:

1. To make some alteration to the decorated function
2. To perform some side effect during module initialization Although Python a module usually looks like a declarative list of functions, it’s important to remember that a module is actually a script that performs side effects (even I/O!) as it loads.

## Example: Property testing

### Hypothesis (Python)

The Hypothesis library has a decorator called `given`. This is one that alters the decorated function.

In the example below, we want to verify the assertion that if you double a number `x`, the result will be greater than or equal to the input. We define a function `test_double` which expresses this.

``````from hypothesis import given
from hypothesis import strategies as st

@given(st.integers())
def test_double(x):
assert x * 2 >= x``````

And we also applied the `given` decorator to it. This replaces the `test_double` function we wrote with a function that runs our function on many inputs in search of an input for which the assertion fails.

``````>>> test_double()
Falsifying example: test_double(x = -1)``````

And we see it did find a counterexample: The property we’re verifying was wrong, because it doesn’t hold for negative numbers.

QuickCheck has a function called `quickCheck` which serves a similar role: The actual type of `quickCheck` is more general than this, but here we give a specialized type for simplicity.

``quickCheck :: Arbitrary a => (a -> Bool) -> IO ()``

`quickCheck` transforms a function which expresses the property into an action which checks the property.

``````testDouble =
quickCheck \$ \x ->
x * 2 >= x``````

And we can run it and see that we get a similar result:

``````λ> testDouble
*** Failed! Falsifiable (after 7 tests and 2 shrinks):
-1``````

Why aren’t we suffering from lack of a decorator syntax in the Haskell example? Because we were able to express the property as a lambda

``\x -> x * 2 >= x``

rather than as a named function

``````testDouble x =
x * 2 >= x``````

and we can pass a lambda directly as an argument to the `quickCheck` function without any fuss.

## Example: Web routing

With Flask, we create a web server by first constructing a `Flask` instance and then adding routes via its `route` method.

``````from flask import *

@app.route("/", methods = ["GET"])
def hello():
return "Hello World!\n"

@app.route("/hello/<name>", methods = ["GET"])
def hello_name(name):
return("Hello " + name + "!\n")``````
``````>>> app.run(port = 8000)
* Running on http://127.0.0.1:8000/ (Press CTRL+C to quit)``````
``````\$ curl http://localhost:8000
Hello World!

\$ curl http://localhost:8000/hello/Julie
Hello Julie!``````

Because Python has no syntax for writing multi-line anonymous functions, we needed two declarations to create each route –

1. Define the route’s behavior by declaring a named function
2. Apply `app.route` to the named function to create the route

– but decorator syntax gave us a nice concise way to perform the second step without having to repeat the name of the function.

Now let’s build the same web server using Scotty.The `scotty` package on Hackage

We will use the `addroute` function which serves a similar role to `Flask.route`:

``addroute :: StdMethod -> RoutePattern -> ActionM () -> ScottyM ()``
``````import Data.Semigroup
import Network.HTTP.Types.Method
import Web.Scotty

app :: ScottyM ()
app =
do
do
text "Hello World!"
addroute GET "/hello/:name" \$
do
name <- param "name"
text ("Hello " <> name <> "!\n")``````
``````λ> scotty 8000 app
Setting phasers to stun... (port 8000) (ctrl-c to quit)``````

In contrast with the Python server, the Haskell routes didn’t require two steps. This is because we didn’t need to name the route behaviors; we just passed them directly as arguments to Scotty’s `addroute` function.

## Example: Timing

### Timing decorator (Python)

For this example we’ll write our own decorator. The `stopwatch` decorator modifies a function so that when the function runs, it also prints a line that says how long it took.

``````from datetime import datetime
import time

def stopwatch(name):
def f(action):
def g(x):
start = datetime.now()
result = action(x)
end = datetime.now()
print(name + ": " + str(end - start))
return result
return g
return f

@stopwatch("delay")
def delay(x):
time.sleep(x)``````
``````>>> delay(1)
delay: 0:00:01.001225``````

### Timing function (Haskell)

Now we’ll do the same thing in Haskell. We’ll be using the `Control.Concurrent` module from `base`, and the `Data.Time.Clock` module from the `time` package.

``````import Control.Concurrent
import Data.Time.Clock

stopwatch :: String -> (a -> IO b) -> (a -> IO b)
stopwatch name action x =
do
start <- getCurrentTime
result <- action x
end <- getCurrentTime
putStrLn (name ++ ": " ++ show (end `diffUTCTime` start))
return result

delay :: Int -> IO ()
delay = stopwatch "delay" \$ \x ->
``````λ> delay 1000000
delay: 1.001164885s``````

Why is the “decorator” (the `stopwatch` function) more concise in Haskell? Because Python requires a decorator to be curried – it is used via three separate invocations

``stopwatch(name)(action)(x)``

rather than taking all arguments at once

``stopwatch(name, action, x)``

– but Python syntax doesn’t easily support currying, so we had to use some funny workarounds like declaring a named function `f` and then returning it.

Using a higher-order function in Haskell is extremely similar to using a decorator in Python. That’s because that’s almost exactly what a decorator is. The Python glossary entry for “decorator” actually defines it as: We find this definition slightly inaccurate; more precisely, a Python decorator is a function that accepts a function argument, and usually (but not necessarily) returns a function.

A function returning another function

So it should be no surprise that this is something at which Haskell excels!

To emphasize the similarity between decorators in Python and higher-order functions in Haskell, let’s put the final examples side-by-side to see how close they are:

``````@stopwatch("delay")
def delay(x):
time.sleep(x)``````
``````delay = stopwatch "delay" \$ \x ->