Last active
September 26, 2024 10:38
-
-
Save brendanzab/04d7ee4cd0e2c96440e939048e6d08f0 to your computer and use it in GitHub Desktop.
Bank account interface as a codata type in Polarity (see: https://polarity-lang.github.io)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- UML Class diagram: | |
-- | |
-- ┌───────────────────────────────────┐ | |
-- │ BankAccount | | |
-- ├───────────────────────────────────┤ | |
-- │ - owner : String | | |
-- │ - balance : Dollars = 0 | | |
-- ├───────────────────────────────────┤ | |
-- │ + getOwner() : String | | |
-- │ + getBalance() : Dollars | | |
-- │ + deposit( amount : Dollars ) | | |
-- │ + withdrawal( amount : Dollars ) | | |
-- └───────────────────────────────────┘ | |
-- | |
-- Based on https://en.wikipedia.org/wiki/File:BankAccount1.svg | |
-- Polarity does not have strings, so just use some hard-coded names | |
data Owner { | |
Alice, | |
Sally, | |
} | |
data Dollars { | |
Z, | |
S(pred: Dollars) | |
} | |
def Dollars.add(other: Dollars): Dollars { | |
Z => other, | |
S(x) => S(x.add(other)) | |
} | |
def Dollars.monus(other: Dollars): Dollars { | |
Z => Z, | |
S(pred) => other.match { | |
Z => S(pred), | |
S(pred') => pred.monus(pred') | |
} | |
} | |
data Option(a: Type) { | |
None(a: Type): Option(a), | |
Some(a: Type, x: a): Option(a) | |
} | |
-- | Bank account interface | |
codata BankAccount { | |
-- | The owner of the account | |
.getOwner: Owner, | |
-- | The current balance in the account | |
.getBalance: Dollars, | |
-- | Deposit some money into the account | |
.deposit(a: BankAccount, amount: Dollars): BankAccount, | |
-- | Withdraw some money from the account, returning `None` in the case of an overdraft | |
.withdrawal(a: BankAccount, amount: Dollars): Option(BankAccount), | |
} | |
-- | Create an account given the owner and the current balance | |
codef AccountState(owner: Owner, balance: Dollars): BankAccount { | |
.getOwner => owner, | |
.getBalance => balance, | |
.deposit(a, amount) => AccountState(owner, balance.add(amount)), | |
.withdrawal(a, amount) => balance.match { | |
Z => None(_), | |
S(_) => Some(_, AccountState(owner, balance.monus(amount))) | |
} | |
} | |
-- | Create a new bank account for a given owner | |
let createAccount(owner: Owner): BankAccount { | |
AccountState(owner, 0) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is related to this issue but depending on how we design it, it might not be sufficient for this use case.