not obsPerPeriod: raise Exception("errorMessageHere") # other related checks... decomposed = seasonal_decompose(data, freq=obsPerPeriod) lessSeasonal = data – decomposed.seasonal lessMedian = lessSeasonal – np.median(data) # and so on and so forth... @chewxy on Twitter
not obsPerPeriod: raise Exception("errorMessageHere") # other related checks... decomposed = seasonal_decompose(data, freq=obsPerPeriod) lessSeasonal = data – decomposed.seasonal lessMedian = lessSeasonal – np.median(data) # and so on and so forth... @chewxy on Twitter
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
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
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
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
return num/denom except ZeroDivisionError: return None def cleanSqrt(x): # special check for x is None, because sqrt(0) == 0 if x < 0 or x is None: return None return math.sqrt(x) @chewxy on Twitter
in v: print(i) >>> v2 = ValueNoIter(1,2,3) >>> for i in v2: print(i) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'ValueNoIter' object is not iterable @chewxy on Twitter
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
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
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 def unit(f): def inner(*args, **kwargs): return Value(f(*args, **kwargs)) return inner def unbox(v): try: return v.value except AttributeError: return v @chewxy on Twitter
__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
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
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