Something went wrong. Try again.
The Monad language. Dependent types, functional programming compiled with LLVM. Hobby project.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129// TODO: see the matching TODO in examples/do_block.mo — `IO`/`println`// are used below (via the companion `open IO {println}`, which is// unaffected) but deliberately NOT listed in THIS `use`; naming anything// here breaks implicit `Monad IO` instance lookup at runtime.#![mote { name := "structs", deps := [init] }]use io {}open IO {println}// Basic struct definitionstruct Point { x: I64, y: I64,}// Struct with default field valuestruct Rect { w: I64, h: I64 := 100,}// Struct with linear field (must be consumed exactly once)struct Buffer { !data: String, size: I64,}#[test]def test_struct_construct_and_match : Bool := let pt : Point := { x := 1, y := 2 } in match pt { mk x y => x + y == 3 }#[test]def test_struct_default_value : Bool := let r : Rect := { w := 50 } in match r { mk w h => h == 100 }#[test]def test_struct_update : Bool := let p1 : Point := { x := 1, y := 2 } in let p2 : Point := { p1 with x := 10 } in match p2 { mk x y => x == 10 && y == 2 }#[test]def test_struct_linear : Bool := let buf : Buffer := { data := "hi", size := 2 } in match buf { mk data size => String.length data == size }#[test]def test_struct_wildcard : Bool := let pt : Point := { x := 99, y := 0 } in match pt { mk x _ => x == 99 }#[test]def test_struct_field_eq : Bool := let pt : Point := { x := 5, y := 5 } in match pt { mk x y => x == y }// Named-field construction sugar: `NAME { field := value, ... }` --// order-independent keyword arguments, matched against NAME's own// declared parameter names -- for both an ordinary `type`'s constructors// and a `def`'s own parameters (the latter declarable as one brace block// too, an alternative spelling of the usual separate parenthesized// groups).type Shape { circle (radius : I64), rectangle (width : I64) (height : I64),}def area (s : Shape) : I64 := match s { circle r => r * r, rectangle w h => w * h }// A def's own parameter list, written as one brace block instead of// separate `(name : Type)` groups -- `scale` in the paren spelling would// be `def scale (factor : I64) (p : I64) : I64 := ...`. `factor`'s `:=`// default only works in this brace form; the paren form has none.def scale {factor : I64 := 2, p : I64} : I64 := factor * p#[test]def test_named_call_constructor_reordered : Bool := // `rectangle`'s own declared order is (width, height) -- given here // in the opposite order, matched by field name, not position. let r : Shape := Shape.rectangle { height := 3, width := 4 } in area r == 12#[test]def test_named_call_constructor_single_field : Bool := let c : Shape := Shape.circle { radius := 5 } in area c == 25#[test]def test_named_call_def_target : Bool := // `scale`'s own params (factor, p) given out of declared order. scale { p := 4, factor := 3 } == 12#[test]def test_named_call_def_target_uses_declared_default : Bool := // `factor` omitted entirely -- falls back to its own `:= 2` default. scale { p := 4 } == 8// Do notation works with a single expressiondef print_point (pt : Point) : IO Unit { match pt { mk x y => println ("(" ++ I64.to_string x ++ ", " ++ I64.to_string y ++ ")") }}def main (args: List String) : IO Unit := let p1 : Point := { x := 10, y := 20 } in let p2 : Point := { p1 with x := 30 } in print_point p1 >>= fn _ => print_point p2