Procedures Back in the old days before C won, Pascal differentiated procedures and functions. SQL does the same. Functions returned values. Procedures didn't. @chewxy on Twitter
Pure Functions In mathematics, a function[1] is a relation between a set of inputs and a set of permissible outputs with the property that each input is related to exactly one output. [1] – "Function" Wikipedia, The Free Encyclopedia. Wikimedia Foundation, Inc. 2015- ish @chewxy on Twitter
Programmers' Definition of Functions May return a value (or not). Return values are not mapped 1:1 with input values Side effects! Do this, then do that (aka procedures). @chewxy on Twitter
Categories A collection of: Things (values) Have an identity function where I(x)
=
x
Arrows (functions) Have domain (input) and range (output) Can be composed Obey some form of associativeness laws TL;DR – Pretty pictures to help us think about functions @chewxy on Twitter
Awkward Squad IO Permanent side effects Concurrency Non-determinism happens Exception Errors – What do we do with malformed/unexpected inputs? FFI Dependence on outside information Even the simple print can fail! @chewxy on Twitter
Domains (input) The domain for div to function correctly: For denom: Any numeric type (int, float, double … ) For num: Any numeric type The domain for sqrt to function correctly: For x: Any numeric type @chewxy on Twitter
Tedious To compose functions, you basically need to create new functions that have different ranges and domains Or do it like what we do normally @chewxy on Twitter
Tedious To compose functions, you basically need to create new functions that have different ranges and domains Or do it like what we do normally Is there a way to generalize? @chewxy on Twitter
Functor In mathematics, a functor[0] is a type of mapping between categories … [0] – More wikipedia citation?? This essay will fail if it's a uni essay @chewxy on Twitter
Interfaces Recap >>>
v
=
Value(1,2,3)
>>>
for
i
in
v:
print(i)
>>>
v2
=
ValueNoIter(1,2,3)
>>>
for
i
in
v2:
print(i)
Traceback
(most
recent
call
last):
File
"",
line
1,
in
TypeError:
'ValueNoIter'
object
is
not
iterable
Interfaces* Monads are anything with bind() and unit(). bind(): applies a function on a monadic value. unit(): makes something a monadic value There are different types of monads, each with different functionalities to their bind() and unit(). Monad Laws apply *Haskell typeclasses are like compile time type safe interfaces @chewxy on Twitter
Maybe Monad Deals with failure conditions bind(): apply a function if the input is not None, else return None
unit(): return the value* * For clarity's sake, we're going to wrap the value in a Value class, which is strictly not necessary @chewxy on Twitter
Example Time def
bind(f):
def
inner(*args,
**kwargs):
a
=
[unbox(i)
for
i
in
args]
kw
=
{k:unbox(v)
for
k,
v
in
kwargs.items()}
if
None
in
a
or
None
in
kw:
return
None
return
f(*a,
**kw)
return
inner
Example Time class
Value(object):
__slots__
=
['value']
def
__init__(self,
v=None):
if
type(v)
is
Value:
self.value
=
v.value
else:
self.value
=
v
def
__repr__(self):
if
self.value
is
not
None:
return
"Just({})".format(self.value)
else:
return
"Nothing"
@chewxy on Twitter
The General Idea Monads help us compose functions that have different return types. Solution: 1. Wrap the value with their contexts in something called a monadic value (which can be anything – you define unit()) 2. Define a function bind() that defines out how to compose the functions that applies within that context @chewxy on Twitter
Other (Possible) Monads Twisted's Deferred (JS promises 10 years before Promises!) djangoORM's .query() and .filter()
*
Scikits-Learn's Pipeline
*
* Yet to check whether it's actually a monad @chewxy on Twitter
Why Does This Matter? We compose functions all the time. Programs should be easy for humans to reason about. We haphazardly recreate solutions to solve certain classes of problems. Understanding the underlying pattern to most of the issues programmers face makes us better (I hope?) BYO paradigm @chewxy on Twitter