type Pair<A: Type, B: Type> {
    left: A,
    right: B,
}

type Box<T: Type> {
    value: T,
    fn rightOf<U: Type>(self: ref<Self>, pair: ref<Pair<T, U>>) -> U {
        return pair.right
    }
}

type PlainBox {
    value: i32,
    fn project<U: Type>(self: ref<Self>, pair: ref<Pair<Self, U>>) -> U {
        return pair.right
    }
}

interface Projector<T: Type> {
    fn project<U: Type>(self: ref<T>, pair: ref<Pair<T, U>>) -> U
}

fn project<T: Projector<T>, U: Type>(value: ref<T>, pair: ref<Pair<T, U>>) -> U {
    return T.project(value, pair)
}

pub fn main() -> Void {
    let box: Box<i32> = Box { value: 1 }
    let pair: Pair<i32, Bool> = Pair { left: 2, right: true }
    let receiver: Bool = box.rightOf(&pair)
    let namespaced: Bool = Box.rightOf(&box, &pair)
    let plain: PlainBox = PlainBox { value: 3 }
    let projectedPair: Pair<PlainBox, Bool> = Pair { left: PlainBox { value: 4 }, right: true }
    let projected: Bool = project(&plain, &projectedPair)
    expect (receiver && namespaced && projected)
}
