| CARVIEW |
HasChor: Functional choreographic programming in Haskell
HasChor is a library for functional choreographic programming in Haskell. See the README.md for more information.
[Skip to Readme]
Modules
[Index] [Quick Jump]
Downloads
- HasChor-0.1.0.1.tar.gz [browse] (Cabal source package)
- Package description (as included in the package)
Maintainer's Corner
For package maintainers and hackage trustees
Candidates
- No Candidates
| Versions [RSS] | 0.1.0.1 |
|---|---|
| Dependencies | async (>=2.2 && <2.3), base (>=4.16 && <4.20), bytestring (>=0.11 && <0.13), containers (>=0.6 && <0.7), HasChor, http-client (>=0.7 && <0.8), random (>=1.2 && <1.3), servant (>=0.19 && <0.21), servant-client (>=0.19 && <0.21), servant-server (>=0.19 && <0.21), split (>=0.2 && <0.3), template-haskell (>=2.18 && <2.22), time (>=1.11 && <1.13), transformers (>=0.5 && <0.7), unordered-containers (>=0.2 && <0.3), warp (>=3.3 && <3.4) [details] |
| Tested with | ghc ==9.6.3, ghc ==9.4.7, ghc ==9.2.8 |
| License | BSD-3-Clause |
| Copyright | (c) Gan Shen 2022 |
| Author | Gan Shen |
| Maintainer | Gan Shen <gan_shen@icloud.com> |
| Uploaded | by gan_shen at 2023-11-13T19:10:18Z |
| Category | Concurrency |
| Source repo | head: git clone https://github.com/gshen42/HasChor this: git clone https://github.com/gshen42/HasChor(tag v0.1.0.1) |
| Distributions | |
| Executables | playground, ring-leader, quicksort, mergesort, kvs4, kvs3, kvs2, kvs1, karatsuba, diffiehellman, bookseller-3-loc-poly, bookseller-2-higher-order, bookseller-1-simple, bookseller-0-network, bank-2pc |
| Downloads | 86 total (2 in the last 30 days) |
| Rating | (no votes yet) [estimated by Bayesian average] |
| Your Rating |
|
| Status | Docs available [build log] Last success reported on 2023-11-13 [all 1 reports] |
Readme for HasChor-0.1.0.1
[back to package description]HasChor
HasChor is a library for functional choreographic programming in Haskell, introduced by our ICFP 2023 paper. Choreographic programming is a programming paradigm where one writes a single program that describes the complete behavior of a distributed system and then compiles it to individual programs that run on each node. In this way, the generated programs are guaranteed to be deadlock-free.
HasChor has the following features:
- HasChor provides a monadic interface for choreographic programming where choreographies are expressed as computations in a monad.
- HasChor is implemented as an embedded domain-specific language, enabling it to inherent features and libraries from Haskell for free.
- HasChor is built on top of freer monads, leading to a flexible, extensible, and concise implementation.
You can find the API specification here.
Usage
From Hackage
Simply list HaChor in your cabal build-depends field, and you're ready to go!
From the Source Repository
Create a cabal.project file and list HasChor's repository as an external source:
packages:
. -- your package
source-repository-package
type: git
location: https://github.com/gshen42/HasChor.git
branch: main
Alternatively, if you want to make changes to HasChor, you could clone the repository and list it as a local package in the cabal.project file:
packages:
. -- your package
./HasChor -- path to HasChor repository
Either way, you can then list HasChor as a dependency in your .cabal file:
build-depends:
, base
, HasChor
A Tour of HasChor
Let's say we want to implement a bookshop protocol with three participants: a buyer, a seller, and a deliverer. The protocol goes as follows:
- The buyer sends the title of a book they want to buy to the seller.
- The seller replies to the buyer with the price of the book.
- The buyer decides whether or not to buy the book based on their budget.
- If yes. The seller sends the title to the deliverer and gets back a delivery date, then forwards it to the buyer.
- If no. The protocol ends.
In HasChor, we could implement the bookshop protocol as the following program:
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeOperators #-}
module Main where
import Choreography (Choreo, cond, locally, mkHttpConfig,
runChoreography, type (@), (~>))
import Control.Monad (void)
import Data.Proxy (Proxy (..))
import System.Environment (getArgs)
buyer :: Proxy "buyer"
buyer = Proxy
seller :: Proxy "seller"
seller = Proxy
deliverer :: Proxy "deliverer"
deliverer = Proxy
priceOf :: String -> Int
priceOf "Types and Programming Languages" = 80
priceOf "Homotopy Type Theory" = 120
priceOf _ = 100
type Date = String
deliveryDateOf :: String -> Date
deliveryDateOf "Types and Programming Languages" = "2002-01-04"
deliveryDateOf "Homotopy Type Theory" = "2013-04-20"
deliveryDateOf _ = "1970-01-01"
budget :: Int
budget = 100
bookshop :: Choreo IO (Maybe Date @ "buyer")
bookshop = do
title <- buyer `locally` \un -> getLine
title' <- (buyer, title) ~> seller
price <- seller `locally` \un -> return $ priceOf (un title')
price' <- (seller, price) ~> buyer
decision <- buyer `locally` \un -> return $ (un price') <= budget
cond (buyer, decision) \case
True -> do
title'' <- (seller, title') ~> deliverer
date <- deliverer `locally` \un -> return $ deliveryDateOf (un title'')
date' <- (deliverer, date) ~> seller
date'' <- (seller, date') ~> buyer
buyer `locally` \un -> do
putStrLn $ "The book will be delivered on " ++ (un date'')
return $ Just (un date'')
False ->
buyer `locally` \un -> do
putStrLn "The book is out of the budget"
return Nothing
main :: IO ()
main = do
[loc] <- getArgs
void $ runChoreography cfg bookshop loc
where
cfg = mkHttpConfig
[ ("buyer", ("localhost", 4242))
, ("seller", ("localhost", 4343))
, ("deliverer", ("localhost", 4444))
]
First, we define a set of locations we will use in the choreography.
Locations are HasChor's abstraction for nodes in a distributed system — they are just Strings.
Since HasChor also uses locations at the type level, we turn on the DataKinds extension and define term-level Proxys (buyer, seller, deliverer) for them.
Next, we have some auxiliary definitions (priceOf, deliveryDateOf, budget) for use in the choreography.
bookshop is a choreography that implements the bookshop protocol:
-
Choreo m ais a monad that represents a choreography that returns a value of typea. Themparameter is another monad that represents the local computation that locations can perform. -
a @ lis a located value that represents a value of typeaat locationl. It's kept opaque to the user to avoid misusing values at locations they're not at. -
locally :: Proxy l -> (Unwrap l -> m a) -> Choreo m (a @ l)is the operator for performing a local compuation at a location. It takes a locationl, a local computationm awith access to a unwrap function, and returns a value atl. The unwrap function is of typeUnwrap l = a @ l -> a, which can only unwrap values atl. -
(~>) :: (Proxy l, a @ l) -> Proxy l' -> Choreo m (a @ l')is the operator for communication between two locations. It turns a value atlto the same value atl'. -
cond :: (Proxy l, a @ l) -> (a -> Choreo m b) -> Choreo m bis the operator for conditional execution. It takes a conditionaatl, a functiona -> Choreo m bdenoting branches, and returns one of the branches.
Finally, we use runChoreography :: Backend cfg => cfg -> Choreo m a -> String -> m a to project the choreography to a particular location and run the resulting program.
runChoregraphy takes a backend configuration cfg which specifies the message transport backend that acutally handles sending and receives messages.
More Examples
HasChor comes with a set of illustrative examples in the examples directory. They are built as executables alongside the HasChor library and can be run with:
cabal run executable-name location