@derive(Copy, Eq, Ord, Hash, Show) pub(api) data Money { minor: i64 } impl Money { pub const ZERO: Money = Money{ minor: 0 } static fn rub(r: i64) -> Money => Money{ minor: r * 100 } static fn zero() -> Money => Money.ZERO static op +(a: Money, b: Money) -> Money => Money{ minor: a.minor + b.minor } static op -(a: Money, b: Money) -> Money => Money{ minor: a.minor - b.minor } static op *(a: Money, k: i64) -> Money => Money{ minor: a.minor * k } static op /(a: Money, k: i64) -> Money => Money{ minor: a.minor / k } } interface Priced { fn price() -> Money } type Sku = distinct str data Product { sku: Sku; title: str; base: Money } impl Product { open fn price() -> Money => base } type Percent = u8 where 0..=90 @sealed data Discounted { embed Product percent: Percent } impl Discounted { init of(p: Product, percent: u8) -> Self | InvalidValue => Self{ Product: p, percent: Percent.from(percent)? } override fn price() -> Money => super.price() - super.price() * (percent as i64) / 100 } fn total(items: List) -> Money pure => items.fold(Money.ZERO, (acc, i) => acc + i.price()) fn main() -> () | InvalidValue io { let book = Product{ sku: Sku("b1"), title: "Book", base: Money.rub(1000) } let d = Discounted.of(book, 15)? assert d.price() == Money.rub(850) print("ok {d.price().minor}") }