MONADS FOR THE WORKING ALCHEMIST WITCHCRAFT

F F U ST F O S T O L MONADS FOR THE WORKING ALCHEMIST WITCHCRAFT

A B O U T T H I S TA L K • The Witchcraft suite: easier algebraic code for Elixir • Don’t need to know Haskell/Idris/PureScript/cat theory, but it helps • Throwing a lot at you (sorry) • Only covering a subset of what’s in these libraries • One takeaway:

B R O O K LY N Z E L E N K A • @expede • Founding partner at Robot Overlord • Runs the Vancouver Functional Programming and Vancouver Erlang/Elixir Meetups • Author of Witchcraft, TypeClass, Algae, Quark, Exceptional, and others • I have Witchcraft stickers (come see me afterwards)

W H AT ’ S I N A N A M E ? witchcraft noun /ˈwɪtʃˌkrɑːft/ 1. the art or power of bringing magical or preternatural power to bear or the act or practice of attempting to do so 2. the influence of magic or sorcery 3. fascinating or bewitching influence or charm 4. an Elixir library

W H AT ’ S S O M Y S T I C A L A B O U T I T ? • High abstraction is powerful but can look intimidating to newcomers • “Monads” • Category theoretic basis • Don’t need to know it • Hask → Ex WAT

WHY ALL THE EXTRA LIBRARIES? MAKING THE CASE

ALGEBRAIC CODE • “Algebra” here just means “a set of rules for manipulating related objects” • You can make your own algebras • Indeed you do without thinking about it • For example, many DSLs and protocols

ALGEBRAIC CODE • High confidence • Reusable abstractions (write once, run in many contexts) • Declarative, pure/concurrent safe code • More tools in your toolbox • Convenience • Well understood, principled, functional design patterns • Lenses, free monad + interpreter, DSLs • Unify similar concepts through abstraction • +/2, ++/2, <>/2, Map.merge/2, MapSet.union/2 have a lot in common (semigroup)

PRINCIPLES DRIVING DESIGN Compatibility with Elixir ecosystem Consistency with mental models Portability from other ecosystems Pedagogy and approachability

I would like to add a slightly different perspective to functional programming in the Erlang VM: functional programming is not a goal in the Erlang VM. It is a means to an end. When designing the Erlang language and the Erlang VM, Joe, Mike and Robert did not aim to implement a functional programming language, they wanted a runtime where they could build distributed, fault-tolerant applications. It just happened that the foundation for writing such systems share many of the functional programming principles. And it reflects in both Erlang and Elixir. – J O S E VA L I M h t t p : / / b l o g . p l a t a f o r m a t e c . c o m . b r / 2 0 1 6 / 0 5 / b e y o n d - f u n c t i o n a l - p r o g r a m m i n g - w i t h - e l i x i r- a n d - e r l a n g /

How can I make this more like Haskell? (Bulb paradox) – B R O O K LY N Z E L E N K A

QUARK • TYPECLASS • ALGAE BOOTSTRAPPING

BOOTSTRAPPING QUARK TYPECLASS WITCHCRAFT ALGAE

QUARK • Classic combinators QUARK TYPECLASS • id, flip, const, and so on • Function composition WITCHCRAFT • Currying • Very important for Witchcraft! • Some constructs must be curried, and for convenience we do this dynamically ALGAE

TYPECLASS • Principled type classes QUARK TYPECLASS • “Classes” and “methods” not the same as in OO • Properties & methods WITCHCRAFT • Hierarchies • Hiding side protocols from API • Enum + Enumerable ALGAE

ALGAE QUARK TYPECLASS WITCHCRAFT • DSL for writing related structs ALGAE

ALGAE defdata All of these fields Roughly “and” defsum One of these structs Roughly “or”

ALGAE

A L G A E . M AY B E • Many uses, but can be “something or failure”

KEEPING IT ELIXIR-Y CONSISTENCY & ETHOS

CONSISTENCY & ETHOS • Introducing these concepts in other languages has been uneven • Scalaz and Swiftz famously called “Haskell fan fiction” • Some Scala looks like Java, some looks like Haskell, and hard to intermingle the two • Elixir • Borrowed the friendly community from Ruby • Data flow and function application over classical expressions and composition • Dynamically typed, or “type checked at runtime”

CONSISTENCY & ETHOS The feeling that we’re trying to avoid

D I R E C T I O N A L I T Y & D ATA F L O W • Let’s bootstrap people’s intuitions! • Elixir prefers diagrammatic ordering D ATA 2 • Important to maintain consistency with rest of language! • Pipes are generally awesome • Want to maintain this awesomeness • What if we just gave the pipe operator superpowers? |> x * 2 4 |> y + 1 5

GIVING PIPES SUPERPOWERS 💪 • Witchcraft operators follow same flow D ATA 2 D ATA [1,2,3] • Data on flows through pointed direction |> x * 2 4 ~> x * 2 [2,4,6] |> • |> becomes ~> (curried map/2) y + 1 5 ~> y + 1 [3,5,7] • Just like pipes

A S Y N C VA R I A N T S Sequential Concurrent

GIVING PIPES SUPERPOWERS 💪 • Operators follow same flow • Data on flows through arrow direction • |> (_) apply/2 • ~> <~ map/2 MORE POWER • ~>> <<~ ap/2 • >>> <<< chain/2

THESE ARE FUNCTIONAL & PRINCIPLED D E S I G N PAT T E R N S

WITCHCRAFT 1.0 HIERARCHY SEMIGROUPOID C AT E G O R Y SEMIGROUP MONOID FOLDABLE FUNCTOR T R AV E R S A B L E A P P LY BIFUNCTOR EXTEND ARROW A P P L I C AT I V E CHAIN COMONAD MONAD

FUNCTOR HIERARCHY FUNCTOR T R AV E R S A B L E A P P LY A P P L I C AT I V E BIFUNCTOR EXTEND CHAIN COMONAD MONAD

FUNCTOR • Provides map/2 (~>), but different from Enum • Always returns the same type of data • No more manual Enum.map(…)|> Enum.into(…)

A P P LY: T H I N K I N G I N S I D E T H E B O X • Provides convey/2 and ap/2 • Embellishes basic function application • Specific embellishment changes per data type

A P P L I C AT I V E : P U T I N T O C O N T E X T • Provide of/2 • Simple: lift values into a datatype • Like List.wrap/1

CHAIN: FUNCTIONS TO ACTIONS • Like Apply & Applicative, but with a special “linking” function • Take raw value • Do something to it • Put the result into the original datatype • Makes it easy to chain functions in a context

POWERING UP GRAPH Application D ATA |> FUNCTION

R E S U LT Functor D ATA ~> FUNCTION

R E S U LT ( S ) Apply D ATA ~>> FUNCTION(S)

R E S U LT ( S ) Chain D ATA

LINKING FUN

R E S U LT ( S )

C H A I N D O N O TAT I O N • Macro to “linearize” chains • Gives us back an operational feel • Great DSLs (seen shortly)

M O N A D I C D O N O TAT I O N • Need to specify the data type • Just add return (specialized Applicative.of/2)

D O N O TAT I O N I M P L E M E N TAT I O N

LET’S SEE SOME CODE! S I M P L E D O - N O TAT I O N U S E S

WRITER MONAD Need to specify more about type in this case Add one to tally Square number We know how many times this has been run, in a pure fashion Run 3x = num ^ 2 ^ 2 ^ 2

WRITER MONAD Log initial value Add a “!” to input and log Return the result Run 3 times Log of transformations

P O W E R I N G U P D ATA F L O W ARROWS

ARROWS 20 4 X / 5 20 INPUT 21 SPLIT 20 4 X + 1 “1” “21” UNSPLIT INSPECT SPLIT UNSPLIT “44121” 21 21 X2 441 OUTPUT

ARROWS

FUTURE DIRECTIONS • More ADTs, more type classes • Pretty printing ADTs • Automatic deriving • Alternate minimal definitions (ex. right_fold or fold_map) • GenArrow

• hex.pm/packages/witchcraft • hex.pm/packages/quark THANK YOU • hex.pm/packages/algae • hex.pm/packages/type_class • @expede • brooklyn@robotoverlord.io