Giter Site home page Giter Site logo

Allow recursive types about variant HOT 7 CLOSED

paarthenon avatar paarthenon commented on May 26, 2024
Allow recursive types

from variant.

Comments (7)

DylanSp avatar DylanSp commented on May 26, 2024 1

Looks great, @paarthenon ! I'll have to give it a try when the opportunity presents itself, but it looks eminently usable.

from variant.

paarthenon avatar paarthenon commented on May 26, 2024

Hey!

Apologies for not responding for so long.

I haven't been able to make recursive variants work yet. It's something I'm experimenting with.

In the meantime, you can do things the "old" way by defining the type manually and then using variants to implement the functionality. It will still work with most of the functions in this library.

Here's an example for you!

interface Var {
    ident: string;
}
interface Apply {
    func: LambdaExpr;
    arg: LambdaExpr;
}
interface Lambda {
    argName: string;
    body: LambdaExpr;
}

type LambdaExpr = 
    | {type: 'Var'} & Var 
    | {type: 'Apply'} & Apply
    | {type: 'Lamda'} & Lambda
;

export const LambdaExpr = variantList([
    variant('Var', fields<Var>()),
    variant('Apply', fields<Apply>()),
    variant('Lambda', fields<Lambda>()),
]);

// creation
const thing = LambdaExpr.Var({ident: 'foo'});
const lambda = LambdaExpr.Lambda({argName: 'bar', body: thing});

// handling recursively
export const printExpression = (expr: LambdaExpr): string => match(expr, {
    Var: ({ident}) => `Var:${ident}`,
    Apply: ({arg, func}) => `Apply (${printExpression(arg)},  ${printExpression(func)})`,
    Lamda: ({argName, body}) => `Lambda:${argName} (${printExpression(body)})`,
});

I know that's not ideal but I hope that can at least allow progress for the moment.

from variant.

DylanSp avatar DylanSp commented on May 26, 2024

That's unfortunate that recursive variants don't currently work; it pretty much rules out using this library for some of my projects. Let us know if you can get them working, it'd be great to see.

from variant.

paarthenon avatar paarthenon commented on May 26, 2024

I understand completely. I'll @mention you if I manage them. Thank you for trying the library!

from variant.

paarthenon avatar paarthenon commented on May 26, 2024

Hi @DylanSp ,

I think I got it. Here is a working code sample from variant 2.0.0-beta.2.

// type def
type LambdaExpr =
    | Variant<'Var', {ident: string}>
    | Variant<'Apply', {func: LambdaExpr, arg: LambdaExpr}>
    | Variant<'Lambda', {argName: string, body: LambdaExpr}>
;

// factory creation
const LambdaExpr = typedVariant<LambdaExpr>({
    Apply: pass,
    Lambda: pass,
    Var: pass,
});

// consumer function
function exprToString(expr: LambdaExpr): string {
    return match(expr, {
        Var: ({ident}) => `(Var: ${ident})`,
        Apply: ({func, arg}) => `(Apply [${exprToString(arg)}] to [${exprToString(func)}])`,
        Lambda: ({argName, body}) => `(Lambda (${argName}): [${body}])`,
    });
}

// creation and use
const expression = LambdaExpr.Lambda({argName: 'alpha', body: LambdaExpr.Var({ident: 'beta'})});
console.log(exprToString(expression));

I hope that meets what you're looking for? This change also includes support for generic variants.

#2 (comment)

See that comment for more details.


If you'd like to try out these (undocumented) changes yourself,

npm i variant@beta

from variant.

paarthenon avatar paarthenon commented on May 26, 2024

Hello again @DylanSp It's been a couple of weeks and variant 2.0.1 including the fix for this issue has been merged in. I'm going to be closing the issue for now. Thank you for bringing this up! Please feel free to reopen this issue or a new one if this approach doesn't address your needs.

from variant.

paarthenon avatar paarthenon commented on May 26, 2024

I haven't updated the docs for this, so I wanted to post here in case it's relevant to you. These changes are available in 2.0.2-beta.6

I added some better handling for recursive generics:

type Tree<T> =
    | Variant<'Branch', {left: Tree<T>, right: Tree<T>}>
    | Variant<'Leaf', {payload: T}>
;

const Tree = genericVariant(({A}) => ({
    Branch: fields<{left: Tree<typeof A>, right: Tree<typeof A>}>(),
    Leaf: payload(A),
}));

const leaf = Tree.Leaf(4); // no need for separate numTree and animalTree constructors.

Attempting to use disparate types raises an error, as expected.

image
If, however, the tree was created with left and right branches set to the generic terms A and B respectively, this no longer raises an error.

p.s. the Variant<string, {}?> type is very simply a stand-in for {type: string} & {}?. I encourage it for ergonomics, and because it's a possible entry point for future 'magic' for me, but it's not necessary.

from variant.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.