packages feed

MultiChor-1.0.0.0: examples/DelegationFig20.hs

{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}

module DelegationFig20 where

{-
let choice : ()+()@[alice, bob] = com[alice][alice, bob] alices_choice;
let query : Query@[alice] = case[alice, bob] choice of
Inl _ => com[bob][alice] bobs_query;
Inr _ => alices_query;
let answerer : (Query@[carroll] -> Response@[carroll])@[carroll] = carrolls_func;
let response = com[carroll][bob, alice] (answerer (com[alice][carroll] query));
case[alice, bob] choice of
Inl _ => bobs_terminal response;
Inr _ => alices_terminal response;
 -}

import CLI
import Choreography
import Data (TestArgs, reference)
import Data.List (sort)
import Data.Maybe (fromMaybe)
import Test.QuickCheck (Arbitrary, arbitrary, arbitraryPrintableChar, elements, listOf1)

$(mkLoc "alice")
$(mkLoc "bob")
$(mkLoc "carroll")

type Participants = ["alice", "bob", "carroll"]

data Args = Args
  { choice :: Bool,
    aliceQ :: String,
    bobQ :: String,
    carrollF :: String
  }
  deriving (Eq, Show, Read)

data Result = Result
  { aliceR :: [String],
    bobR :: [String],
    carrollR :: [String]
  }
  deriving (Eq, Show, Read)

instance TestArgs Args Result where
  reference Args {choice, aliceQ, bobQ, carrollF} =
    let f = fromMaybe carrollsDefault $ carrollF `lookup` carrollsFunctions
        result = f $ if choice then aliceQ else bobQ
     in Result {aliceR = [result | choice], bobR = [result | not choice], carrollR = []}

instance Arbitrary Args where
  arbitrary =
    Args
      <$> arbitrary
      <*> listOf1 arbitraryPrintableChar -- Avoiding wierd behavior of CLI on empty outputs :(
      <*> listOf1 arbitraryPrintableChar
      <*> elements (fst <$> carrollsFunctions)

carrollsFunctions :: [(String, String -> String)]
carrollsFunctions =
  [ ("reverse", reverse),
    ("alphabetize", sort)
  ]

carrollsDefault :: String -> String
carrollsDefault = const "No Handler"

mainCho :: Choreo Participants (CLI m) ()
mainCho = do
  choice <- (alice, getInput "Alice's choice:") -~> alice @@ bob @@ nobody
  query <-
    flatten (alice @@ nobody) (alice @@ nobody)
      <$> cond (explicitSubset, (refl, choice)) \case
        False -> (bob, getstr "Bob's query:") -~> alice @@ nobody
        True -> alice `_locally` getstr "Alice's query:"
  answerer <-
    carroll `_locally` do
      handlerName <- getstr "Carrol's function (reverse or alphabetize):"
      return $ fromMaybe carrollsDefault $ handlerName `lookup` carrollsFunctions
  query' <- (alice, query) ~> carroll @@ nobody
  response <- (carroll, \un -> return $ un carroll answerer (un carroll query')) ~~> alice @@ bob @@ nobody
  (_ :: Located '["alice", "bob"] ()) <- cond (explicitSubset, (refl, choice)) \case
    False -> bob `locally_` \un -> putstr "Recieved:" (un bob response)
    True -> alice `locally_` \un -> putstr "Recieved:" (un alice response)
  return ()