mlhaufe / brevity

Brevity is a library that enables Feature-Oriented Programming (FOP) and solves the expression problem in a manner that makes data and operation declarations trivial to define and compose.
GNU Affero General Public License v3.0
1 stars 0 forks source link

Multimethods #70

Open mlhaufe opened 1 year ago

mlhaufe commented 1 year ago

References:

Pattern could be leveraged, but how would this work with the trait declaration?

Perhaps the camelCase naming convention would work?

This feature does raise an interesting question: Is Brevity becoming a Relational DSL?

Instead of complected = data + traits, it would be data + multimethods. Starting to rhyme with Julia?

What of encapsulation and open-recursion? Slate may be more useful here, but Slate relies on mutable prototypes...

Note that Haskell can't do this.

Gilad is not a fan (because of runtime cost?): https://gbracha.blogspot.com/2009/09/systemic-overload.html

mlhaufe commented 1 year ago

Interesting comments on LtU:

Multiple Dispatch in Practice

There is some agreement with my thoughts that Pattern could be leveraged here. If this could be made modular (tied to an Algebra), then maybe that's the trick. Use the Dylan algorithm and merge with my pattern matching form

mlhaufe commented 1 year ago

Research paper: Modular Statically Typed Multimethods

Another LtU thread:

http://lambda-the-ultimate.org/node/5322

mlhaufe commented 1 year ago

Is there such a thing as a super call in multimethods? Whose super?

Open-Recursion support seems to make this feature explode in possible callers when spread across a code-base.

Do Multimethods in general violate the Open-Closed Principle?

mlhaufe commented 1 year ago

Is there such a thing as a super call in multimethods? Whose super?

With multimethods associated with the family, super would be the family parent

mlhaufe commented 1 year ago

Here's my thoughts on the new form:

const Shape = family((Shape) => ({
    Circle: { r: Number },
    Square: { side: Number },

    collides: [
        { s1: Shape, s2: Shape, $(o) { },
        { s1: Shape, s2: Shape.Circle, $({ s1, s2 }) { } },
        { s1: Shape.Circle, s2: Shape.Square, $({ s1: c, s2: s }) { } }
    ]
}))

const Peano = family((Peano) => ({
    Zero: {},
    Succ: { pred: Peano },

    isZero: [
        { pred: Peano.Zero, $() { return true } },
        { pred: Peano.Succ, $() { return false } }
    ]
}))

const List = family((List, T) => ({
    Nil: {},
    Cons: {head: T, tail: List(T) },

    length: [
        {xs: List.Nil, $(){ return 0 } },
        {xs: List.Cons, $({tail}){ return 1 + this.length(tail)} }
    ]
}))
mlhaufe commented 1 year ago
const Shape = family((Shape) => ({
    Circle: { r: Number },
    Square: { side: Number },

    collides: [
        $({ s1: Shape, s2: Shape })(() => { throw new TypeError('Unhandled shapes') }),
        $({ s1: Shape.Circle, s2: Shape.Circle })(() => { }),
        $({ s1: Shape.Circle, s2: Shape.Square })(() => { }),
        $({ s1: Shape.Sqaure, s2: Shape.Circle })(() => { }),
        $({ s1: Shape.Square, s2: Shape.Square })(() => { }),
    ]
}))

I don't know how the multimethods would work with mult-sorted algebras:

// Multi-Sorted
const Stmt = family(IntBoolExp, (Self) => ({
    Var: {name: String}, // E
    Assign: {name: String, e /* E */}, // E

    Expr: {e /* E */}, // S
    Seq: {first /* S */, second /* S */} // S
}))