Skip to content

Draft: Generics & Contracts

Felix Schoeller edited this page Jun 17, 2020 · 2 revisions

// the file “…” notation just means, that this is in file map.kan

file “map.kan” {

// A contract contains a list of statements, which must be valid for the given
// type parameters (here just T)
// In this case, it just means that a variable of type *T must have a method named hash, which
// returns and i32
type Hash[T] contract {
    let t: *T = undefined
    let h: i32 = t.hash()
}

// Entry takes 2 type parameters. K is bound by the Hash contract, since we need
// to hash the Key.
// V is unbound. It could be any type
type Entry[K: Hash, V] struct {
    key: K,
    value: V
}

// The HashMap basically inherited the bounds of Entry, since it needs those for the entries
// array
type HashMap[K: Hash, V] struct {
    len: i32,
    // An array containing an unknown amount of Entry[K, V] struct instances
    entries: []Entry[K, V]
}

// the insert function needs K and V, which are implicitly bound by Map[K, V]
def [K, V] (m: *Map[K, V]) insert() {
    let entries: []Entry[K, V] = m.entries;
    // ...
}

}

file “person.kan” {

type Person struct {
    name: string
}

def (p: *Person) hash(): i32 {
    let hash = 0;
    for let i = 0; i < p.name.len; i += 1 {
        hash += p.name[i];
    }
    return hash;
}

}

file “main.kan” {

import "map" as m
import "person" as p
import "math"

type Number[n: T] contract {
    n = n + n
    n = n * n
    n = n / n
    n = n - n
}

type Vector[v: V, Scalar: Number] contract {
    let s: Scalar = undefined
    v = v.add(&v)
    v = v.scale(s)
    s = v.len()
}

type Vec2 struct {
    x: f32,
    y: f32
}

def (self: Vec2) add(other: Vec2): Vec2 {
    return Vec2 { x: self.x + other.x, y: self.y + other.y }
}

def (self: Vec2) scale(scalar: f32): Vec2 {
    return Vec2 { x: self.x * scalar, y: self.y * scalar }
}

def (self: Vec2) len(): f32 {
    return math.sqrt(self.x * self.x + self.y * self.y)
}

type MyPerson new = p.Person

def (p: *MyPerson) hash(): i32 {
    return 0
}

def main() {
    let felix = p.Person { name: "felix" }

    felix.hash()

    let map1: m.Map[p.Person, string] = ...
    let map2: m.Map[MyPerson, string] = ...

    map.insert(felix, "123")
}

}

file “print.kan” {

type Print[t: T] contract {
    t.print()
}

type Display[T] contract {
    let t: T = undefined
    let s: string = t.to_string()
}

def [T: Print] print(s: []T) {
    for let i = 0; i < s.len; i += 1 {
        s[i].print();
    }
}

def [T: Display] to_string(s: []T): []string {
    let ret: []string = new [string, s.len];
    for let i = 0; i < s.len; i += 1 {
        ret[i] = s[i].to_string()
    }
    return ret
}

}

Clone this wiki locally