Giter Site home page Giter Site logo

professorg / haschor Goto Github PK

View Code? Open in Web Editor NEW

This project forked from gshen42/haschor

0.0 0.0 1.0 177 KB

Functional choreographic programming in Haskell

Home Page: https://gshen42.github.io/HasChor/

License: BSD 3-Clause "New" or "Revised" License

Haskell 94.03% Nix 5.97%

haschor's Introduction

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 inherit 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:

  1. The buyer sends the title of a book they want to buy to the seller.
  2. The seller replies to the buyer with the price of the book.
  3. The buyer decides whether or not to buy the book based on their budget.
    1. If yes. The seller sends the title to the deliverer and gets back a delivery date, then forwards it to the buyer.
    2. 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 a is a monad that represents a choreography that returns a value of type a. The m parameter is another monad that represents the local computation that locations can perform.

  • a @ l is a located value that represents a value of type a at location l. 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 location l, a local computation m a with access to a unwrap function, and returns a value at l. The unwrap function is of type Unwrap l = a @ l -> a, which can only unwrap values at l.

  • (~>) :: (Proxy l, a @ l) -> Proxy l' -> Choreo m (a @ l') is the operator for communication between two locations. It turns a value at l to the same value at l'.

  • cond :: (Proxy l, a @ l) -> (a -> Choreo m b) -> Choreo m b is the operator for conditional execution. It takes a condition a at l, a function a -> Choreo m b denoting 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. runChoreography takes a backend configuration cfg which specifies the message transport backend that acutally handles sending and receiving messages. This example uses HasChor's HTTP backend, which implements the Backend typeclass. Alternate implementations of Backend could use different message transport mechanisms.

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

Further Readings

haschor's People

Contributors

gshen42 avatar shumbo avatar lkuper avatar lastland avatar professorg avatar jackoe avatar shapeofmatter avatar

Forkers

lastland

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.