Skip to content

Latest commit

 

History

History
287 lines (227 loc) · 16.1 KB

haskell-effects.org

File metadata and controls

287 lines (227 loc) · 16.1 KB

Effects in Haskell - A review of the state of the art.

Pre-requisites

Overview/review of

  • [X] Arrows
  • [X] Categories
  • [X] Bifunctors (covariant functors on two arguments)
  • [X] Profunctors (functors on two args respectively contra/co-variant)
  • [X] Free monads
  • [X] Final tagless
  • [X] Algebraic Effects

The categorical imperative

Intro to Category Theory

List of references (important/seminal papers wot I av red or am)

PaperAuthorNotes
Programming with arrowsJohn HughesSeminal arrows
Applicative programming with effectsConnor McBride, Ross PatersonSeminal applicative functors
Idioms are oblivious…Sam Lindley, Phil Wadler, Jeremy WallopTheoretical comparison (a bit theory rich for my level)
Category Theory for ProgrammersBartosz MilewskiGateway drug to cat theory (five star recommendation)
Compiling embedded languagesConal Elliot, et.al.Practical development of embedded language
Data types a la carteWouter WesistraInfluential Functional pearl solving Wadler’s “expression problem”
Typed Tagless Final interpretersOleg KiseylovAlso influential approach to expression problem and much more
Composing effects into tasks and workflowsRichard Eisenberg et.al.TODO
Free applicative functorsPaulo Capriotti, Ambrus KaposiTODO
Freer monads more extensible effectsOleg Kiseylov, Heromi IbdiTheoretical basis of most modern Free monad implementations
Generalising monads to arrowsJohn HughesMore arrows from the inventor
Computational lambda caculus and monadsEugenio MoggiSeminal monad paper
Notions of compuatations as monoidsExequiel Rivas, Mauro JaskelioffA unifying categorical look at all the functors
Combining deep and shallow embeddings of DSLsJosef Svenningsson, Emil AxelsonHave your cake and eat it too absraction of eDSls
The arrow calculusYallop, Lindley, WadlerTODO Type theoretic look at arrows

State of art in Haskell libraries and frameworks

Evaluate (see matrix) for following approaches:

PackagePrincipal AuthorNotes
polysemySandy Maguire
freer-simpleAlexis King
effAlexis King+ghc delimited continuations proposal
cleffdaylily
effectfulAndrzej RybczakBenchmarks
kermantleRichard EisenbergComposing binary effects into (data) workflows
hfmAlexander GraninFunctional Design and Architecture HFM mostly pointless
fused-effectsPatrick ThompsonStrange loop 2019 talk

Binary Effects (Eisenberg)

  1. Model them as (G)ADTs and write interpreter functions
  2. Compose them from regular applicative/monadic effects (Reader, Writer, State etc.)
  3. Reuse existing binary effects (Categories, Arrows, Profunctors etc.)
  4. Take the Product (from bifunctors) of 2 different binary effects. They are composed in parallel: results from one cannot be passed to the other.

Free monads

What are Free Monads?

Here’s an even simpler answer: A Monad is something that “computes” when monadic context is collapsed by

join :: m (m a) -> m a
  

recalling that >>= can be defined as

x >>= y = join (fmap y x)
  

This is how Monads carry context through a sequential chain of computations: because at each point in the series, the context from the previous call is collapsed with the next.

A free monad satisfies all the Monad laws, but does not do any collapsing (i.e., computation). It just builds up a nested series of contexts. The user who creates such a free monadic value is responsible for doing something with those nested contexts, so that the meaning of such a composition can be deferred until after the monadic value has been created.

An Introduction to Free Monads So far this is my favorite Free monad tutorial (highly recommended if theoretical underpinnings are important for ones understanding) and very well written and structured with examples and exercises.

Using free monads, we can define a computation as a data structure. Here, “computation” is a very broad term. The data structure in question doesn’t define how the computation is performed, and we can write a separate interpreter (or indeed many interpreters) that performs the actual computation in question.

Articles/Posts of NoteAuthor
Free monads considered harmfulMark Karpov
Why free monads matterGabriella Gonzales
What does free buy us?Matt Parsons
The path to Haskell complexitiesVitaly Bragilevsky
Monads for freeEdward Kmett
Introduction to Free MonadsNikolay Yakimov
Free Monads for Cheap InterpretersJames Haydon
Introduction to tagless finalVasiliy Kevroletin
HFM mostly pointlesseffectfully
Mother of all monadsDan Piponi

TODO: Summarize: Alexis King - unresolved challenges of scoped effects (twitch cast)

Continuation Monads cannot form a Lawvere theory.

LectureAuthor
A categorical view of computational effectsEmily Riehl

This is a very accessible and fresh view of effects by a Cat theorist and might explain why there is a problem at the heart of the Free monad approach.

Alexander Granin - Functional Design and Architecture: Free monads, DSLs

TLDR;

Caution: Alexander’s writing style makes it easy to doubt his seriousness (something that has invited vitriolic attack on his claims for hierarchical free monads (HFM) but not referenced here at the request of that author; a more measured critique is available at HFM mostly pointless)

While most of the content of the (MEAP) edition of the book addresses general design principles, rather than effects systems per-se; there is a overview of composing Free monads w.r.t defining and dispatching DSL’s.

My advice would to be to jump in at Chapter 7. for a summary around stateful applications even if the (long running) examples will not be so clear as a result maybe read Chapter 6. which details the application of free monads in the construction of eDSLs if you are not familiar with Free monads.

He jumps around in his development and often the conclusions and exposition are left deferred for future sections/writing. E.g. I’m still waiting for the section on logging to be satisfactorily concluded.

The main tenets of his thesis are:

  1. Do structured design using common patterns adapted for FP.
  2. eDSLs and respective interpreters are a goto pattern for functional design.
  3. Free monads (Hierarchical Free Monads) are a powerful way to construct eDSLs.

Here some quotes from the book that give a flavour of the approach:

Chapter 2 The basics of functional declarative design

In functional programming, it’s good to have an architecture in two forms:

  • Topology of layers, modules, and subsystems. This can be either described by diagrams or implemented in the project structure. The hints for how to define functionality for modules lie in our requirements model, and we will extract them from mind maps directly.
  • DSL interfaces for domain model, subsystems, and services. A set of DSLs on top of a subsystem can be thought of as the functional interface of that system. We can use model-driven development to build DSLs for our domain model.

In this architecture approach, it becomes clear that Free monadic eDSLs should interact somehow when this makes sense. If we want to place the methods of the two Free languages into the same script, this script should know about both of the languages. This is where the idea of Free monad effect systems occurs, - but it occurs in the community, not in FDD. I’m proposing another way, that is simpler and quite enough for doing impressive things. Free monadic languages can be nested. Methods of a language can refer to other languages, and this helps to build hierarchies of Free monads. I call this approach Hierarchical Free Monads (HFM)…

Chapter 5 Embedded domain-specific languages

Software development is a difficult job. Developers do make wrong decisions, and it happens more often than it actually should. Developers do write incorrect code, and it happens against their will most likely. Developers feel lost in complex business domains, broad and contradictory requirements, and mind-bending technologies, each of which can turn anyone into depression when something goes wrong. Nothing is perfect; nobody is a superman.

Chapter 6 Domain modeling with Free monads

6.1.1 The Free monad pattern

The Free monad, which comes from the depths of category theory, is used to wrap some (but not all) types into a monad. Applications of the Free monad usually live in the academic part of functional programming, but there is one important functional pattern we can adopt in practical development. The Free monad pattern helps you to separate subsystem interface from subsystem implementation and provide an eDSL that your clients can use to describe scenarios for your subsystem without knowing the implementation details. In this case, an eDSL will be a free monadic language that reflects the logic of your subsystem in a safe, concise way.

There are three key points of this pattern:

  • declarative Free monad eDSL;
  • declarative Free monadic scenarios of one’s business logic and domain;
  • Free interpreters to sew the declarations and implementations.

I won’t be probably wrong if I say that most of the codebases don’t even try to keep business logic pure, separated from the real IO. Most of the codebases work in the IO instantly, and such code isn’t interpretable, it’s immediately evaluable.

It’s a bit more difficult to explain why the crafty recursive Free type reduces everything to a single type. But it really does. It acts as a Russian nesting doll and does so on both levels: on the value level, and on the level of types.

Essentially, the Free type represents the fixed point combinator. In turn, the fixed point combinator is a fundamental representation of recursion in lambda calculus.

As you can see, the Free monad pattern has a lot of advantages over the algebraic interfaces we were creating earlier. But there are some disadvantages too:

  • Because it’s a monad, the user should know monads well to use your language.
  • The Free monad requires that the language be a functor. Although it’s an easy transformation for your language, you need to understand what it’s for. However, other Free monads such as Church-encoded Free monads, do not have this restriction. But possibly have their own, so the topic is a bit wider than described in this introductory chapter.
  • The theory behind the Free monad is complex. For example, the Free type has a recursive value constructor that’s kind of the fixpoint notion (the mathematical concept of recursive operation). Also, converting a language into the Free monad form looks like a magical hack. But it’s not magic, it’s science. The good thing is that you can use the Free monad in practice without knowing the theory at all.
  • It’s hard (sometimes impossible) to convert your language into the Free monad form when it’s made of advanced functional concepts: GADTs, phantom types, type-level logic, and so on. This probably means you need another approach to the problem.
  • Some implementations of the Free monad can be slow as they approximate O(n^2) in the binding mechanism. But there are other Free monads, so this is not a problem.