Re:A Gentle Intro to Monads … Maybe?
by tel on Friday January 17, 2014 @03:42PM
(#7078273)
Okay, I'll explain it. Apologies for the apparent contradiction—I'm not trying to move the goal posts, just trying to avoid going into the weeds.
As I said, Python decorators are essentially just a syntax for function composition.
@deco
def g(args): g := deco(g(args): body)
body
where (g := a) means a is assigned to the name g. As it turns out, functions form a type which is a functor over the result type. The fmap (arrow map) is just function composition. In Haskell you would write this as
instance Functor ((->) r) where
fmap g f = g . f
where the (.) syntax is also function composition, very similar to the @deco syntax in Python. In this sense, I stated that @deco is a Functor.
Now, the function data type also admits a Monad instance (which some people abuse terminology to say "functions are monads" but I highly dislike that terminology when speaking carefully).
instance Monad ((->) r) where
return a = \_ -> a
(f >>= g) x = g (f x) x
So in this way, the function type instantiates both Functor and Monad, but composition (which is (.) in Haskell and @deco is Python) is not directly related to the Monad.
Instead, a function's Monad instance allows us to "defer application" and translate something like
\x -> (1 + x, 2 + x)
into
do a <- (1+)
b <- (2+)
return (a, b)
In this format it's pretty stupid looking, but we also tend to call this monad instance the "Reader Monad" which indicates computations which occur under a fixed set of configuration information—some static global variables.
For instance, if I had a Key type which represented some encryption key I could change my encrypt and decrypt functions from
which, allows us to defer that extra `Key` argument until later.
So, that's what I meant by saying that @deco isn't the Monad that its Functor represents—it only has the composition aspect, not the deferred application aspect.
As I said, Python decorators are essentially just a syntax for function composition.
where (g := a) means a is assigned to the name g. As it turns out, functions form a type which is a functor over the result type. The fmap (arrow map) is just function composition. In Haskell you would write this as where the (.) syntax is also function composition, very similar to the @deco syntax in Python. In this sense, I stated that @deco is a Functor.Now, the function data type also admits a Monad instance (which some people abuse terminology to say "functions are monads" but I highly dislike that terminology when speaking carefully).
So in this way, the function type instantiates both Functor and Monad, but composition (which is (.) in Haskell and @deco is Python) is not directly related to the Monad.Instead, a function's Monad instance allows us to "defer application" and translate something like
into In this format it's pretty stupid looking, but we also tend to call this monad instance the "Reader Monad" which indicates computations which occur under a fixed set of configuration information—some static global variables.For instance, if I had a Key type which represented some encryption key I could change my encrypt and decrypt functions from
to which, allows us to defer that extra `Key` argument until later.So, that's what I meant by saying that @deco isn't the Monad that its Functor represents—it only has the composition aspect, not the deferred application aspect.