MultiChor is a library for writing choreographic programs in Haskell.
That means you write one program, a "choreography" which seamlessly describes the actions of many communicating machines; these participants can be native Haskell threads, or various humans' laptops communicating over HTTPS, or anything in between. Each of these "endpoints" will "project" their behavior out of the choreography.
Choreographies aren't just easier to write than distributed programs, they're automatically deadlock-free!
MultiChor uses some of the same conventions and internal machinery as HasChor, but the API is incompatible and can express more kinds of choreographic behavior.
- The heart of the MultiChor library is a choreography monad
Choreo ps m a
.ps
is a type-level list of parties participating in the choreography,m
is an monad used to write local actions those parties can take,a
is the returned value, typically this will be aLocated
orFaceted
value as described below.
- MultiChor is an embedded DSL, as interoperable with the rest of the Haskell ecosystem as any other monad. In particular, MultiChor gets recursion, polymorphism, and location-polymorphism "for free" as features of Haskell!
- MultiChor uses multicast and multiply-located values, as introduced in We Know I Know You Know.
- A value of type
Located ls a
is a singlea
known to all the parties listed inls
. In a well-typed choreography, other parties, who may not know thea
, will never attempt to use it. - In the expression
(s, v) ~> rs
, a senders
sends the valuev
to all of the recipients inrs
, resulting in aLocated rs v
. - For easy branching in choreographies, the primitives
enclave
andnaked
combine to formcond
.(parties, guard) `cond` (\g -> c)
unwraps aLocated parties g
for use as a nakedg
in the conditional choreographyc
.
- A value of type
- Safe handing of parties, party-sets, and located values is enforced using Ghosts of Departed Proofs.
In particular, instead of specifying the party
"alice"
in a choreography as aString
or aProxy "alice"
, they're specified by aProof
that the type-level"alice"
is present in the choreography and has access to the relevant values. MultiChor provides utilities to write these proofs compactly. - In addition to location polymorphism, MultiChor allows you to write choreographies
that are polymorphic with respect to the number of parties in a polymorphic party-set.
This is trivial if they're passively receiving values; new primitives allow them to actively communicate:
fanOut
lets a single party send different values (of the same typea
) to a list of partiesrs
, resulting in aFaceted rs a
.fanIn
lets a list of partiesss
each send a value to the same partiesrs
, resulting in aLocated rs [a]
.- A
x :: Faceted ps a
represents distincta
s known to each ofps
respectively.
- MultiChor allows parallel behavior of many parties to be concisely expressed.
parallel
lets many parties perform local monadic actions in parallel using theirLocated
andFaceted
values; the return isFaceted
.congruently
lets many parties perform the same pure computation in parallel, using only theirLocated
values; the return isLocated
.
Many example choreographies are presented in the examples directory.