見出し画像

Epoch#234 | Marloweチュートリアル8章

こんにちは。カルダノのステーク・プール・オペレータのSUGARです。Marloweのチュートリアルを少しずつ読んでみています。今回の八章はHaskellでのプログラミング要素多目になります。

そもそも「Marloweとは?」など、過去の記事をブログまとめページにまとめていますので、こちらもよろしくお願いします。

8. Haskellに埋め込まれたMarlowe

このチュートリアルでは、エスクローの例に戻り、HaskellでMarloweの埋め込みを使用して、より読みやすく、モジュール化された再利用可能なMarloweコントラクトの記述を作成する方法を紹介します。

エスクロー(escrow):商取引の際に信頼の置ける第三者を仲介させて取引の安全を担保する第三者預託である。(ウィキペディアより)

8.1. 簡易エスクロー・コントラクト、再訪

画像1

以前のチュートリアルでこのMarloweコントラクトを開発したことを思い出してください。

そこでは "monolothic "なコントラクトとして提示しましたが、Haskellの定義を使用することで、より読みやすくすることができます。まず、最初のコミットメントをコントラクト内部の作業部分から分離することができます。

contract :: Contract
contract = When [Case (Deposit "alice" "alice" ada price) inner]
               10
               Close
inner :: Contract
inner =
 When [ Case aliceChoice
             (When [ Case bobChoice
                         (If (aliceChosen `ValueEQ` bobChosen)
                            agreement
                            arbitrate) ]
                   60
                   arbitrate)
       ]
       40
       Close

ここでの用語の多くは、それ自体がHaskellの中で定義されています。主に、アリスとボブの間で合意があった場合に何が起こるかを扱う2つの契約があり、合意がなかった場合には、キャロルは2人の間でどのように仲裁するべきかを扱います。

agreement :: Contract
agreement =
 If
   (aliceChosen `ValueEQ` (Constant 0))
   (Pay "alice" (Party "bob") ada price Close)
   Close

arbitrate :: Contract
arbitrate =
 When  [ Case carolClose Close,
         Case carolPay (Pay "alice" (Party "bob") ada price Close) ]
       100
       Close

これらの契約では、以下のような簡単な略語も使用しています。

price :: Value
price = Constant 450

これは猫の価格、つまりエスクロー中のお金の価値を示しています。

アリスとボブが行った選択を記述することもできます。選択が行われていない場合に備えて、デフォルト値の defValueも求められていることに注意してください。

aliceChosen, bobChosen :: Value

aliceChosen = ChoiceValue (ChoiceId choiceName "alice")
bobChosen   = ChoiceValue (ChoiceId choiceName "bob")

defValue = Constant 42

choiceName :: ChoiceName
choiceName = "choice"

選択肢を記述する際には、数値に適切な名前をつけることができます。

pay,refund,both :: [Bound]
pay    = [Bound 0 0]
refund = [Bound 1 1]
both   = [Bound 0 1]

新しい関数(または「テンプレート」)を自分たちで定義します。この場合は下記を定義します。

choice :: Party -> [Bound] -> Action
choice party bounds =
 Choice (ChoiceId choiceName party) bounds

選択肢の表現をもう少しシンプルにして読みやすくするための方法として、

alicePay, aliceRefund, aliceChoice :: Action
alicePay    = choice "alice" pay
aliceRefund = choice "alice" refund
aliceChoice = choice "alice" both

これらすべての定義を考えると、このセクションの冒頭にあるコントラクトを、その意図を明確にするような書き方で書くことができます。「純粋な」Marloweで書くか、あるいはこれらの定義を拡張して書くと、代わりにこのようなコントラクトになります:

When [
 (Case
    (Deposit
       "alice" "alice" ada
       (Constant 450))
    (When [
          (Case
             (Choice
                (ChoiceId "choice" "alice") [
                (Bound 0 1)])
             (When [
                (Case
                   (Choice
                      (ChoiceId "choice" "bob") [
                      (Bound 0 1)])
                   (If
                      (ValueEQ
                         (ChoiceValue
                            (ChoiceId "choice" "alice"))
                         (ChoiceValue
                            (ChoiceId "choice" "bob")))
                      (If
                         (ValueEQ
                            (ChoiceValue
                               (ChoiceId "choice" "alice"))
                            (Constant 0))
                         (Pay
                            "alice"
                            (Party "bob") ada
                            (Constant 450) Close) Close)
                      (When [
                            (Case
                               (Choice
                                  (ChoiceId "choice" "carol") [
                                  (Bound 1 1)]) Close)
                            ,
                            (Case
                               (Choice
                                  (ChoiceId "choice" "carol") [
                                  (Bound 0 0)])
                               (Pay
                                  "alice"
                                  (Party "bob") ada
                                  (Constant 450) Close))] 100 Close)))] 60
                (When [
                      (Case
                         (Choice
                            (ChoiceId "choice" "carol") [
                            (Bound 1 1)]) Close)
                      ,
                      (Case
                         (Choice
                            (ChoiceId "choice" "carol") [
                            (Bound 0 0)])
                         (Pay
                            "alice"
                            (Party "bob") ada
                            (Constant 450) Close))] 100 Close)))
     ]

演習
ページの上部にあるコントラクトに、他にどのような略語を追加できますか?
コントラクトを短くしたり、よりモジュール化したりするために定義できる関数はありますか?

この例では、Haskell の基本的な機能である定数や関数の定義を再利用するだけで、Haskell の埋め込みがどのようにしてより表現力のある言語を提供してくれるのかを示しました。次のチュートリアルでは、JavaScript の埋め込みを使用してコントラクトを定義する方法を学びます。

留意事項
・このコントラクトは EscrowSimpleV2.hs のモジュールに含まれています。(現在リンク先は404)
・拡張バージョンはMarlowe プレイグラウンドから来ており、純粋なMarloweへの埋め込み定義の拡張をサポートしています。

-----

Monolothic:モノリシック、一本石の(ような)、がっしりとかたまっている、一枚岩的な、完全に統制された、画一主義的な
Marlowe: Marlowe
Contract(契約書):コントラクト
Contract(契約):契約
Omniscient:全知全能
Fungible: 同等のタイプや価値のものと交換しやすいもの。等価交換可能
Account: アカウント
Value: 値
Observation: オブザベーション
Action: アクション
Role: 役割
Party: 当事者となる集団、パーティ
セマンティクス: プログラムが持つ意味

-----

最後まで読んでいただき、本当にありがとうございます。
役に立ったと思っていただけたら、スキや、Twitterのフォローをしていただけると幸いです。

過去のブログのまとめページもよろしくお願いします。(ステークプールの宣伝を含みます)

この記事が気に入ったらサポートをしてみませんか?