New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typescript typings #65

Open
djleonskennedy opened this Issue Jan 17, 2017 · 17 comments

Comments

Projects
None yet
7 participants
@djleonskennedy

djleonskennedy commented Jan 17, 2017

Hello
Is there in plans to add typescript bindings to "folktale" ?

@robotlolita

This comment has been minimized.

Show comment
Hide comment
@robotlolita

robotlolita Jan 17, 2017

Member

Unlikely for now, the type system implemented by TypeScript (and Flow) are not expressive enough to support most of the constructs that Folktale uses, so you'd just end up with a lot of any types, which is not very useful. Folktale was not written for a particular type system, which makes this a bit difficult too (as the features require many advanced type system techniques).

Depending on how Flow and TypeScript advance in the future I might look into this again, though.

Right now Folktale requires at the very least three type system features:

  • Parametric polymorphism, the ability of writing a generic type over some parameters, and then specialising that later. Maybe<a>, Either<a, b>, etc. all require this. Both Flow and TypeScript support this (some people refer to them as "generics");

  • Higher-Kinded polymorphism, the ability of writing a generic type that you can pass around, and yield new types. Imagine the above, but Maybe is just as valid a usage as Maybe<a>, it just results in a "type function" where the thing you're passing the type to is supposed to provide the argument for Maybe to construct a type. This is required for monads and applicatives. The type of .apply is:

    apply :: forall a, b, c. (Applicative a) => (this: a<b → c>, a<b>) → a<c>
    

    The (Applicative a) => part just says "the type variable a is constrained to be an Applicative". Since we're using an object-oriented language we could just specialise this instead:

    apply :: forall b, c. (this: Maybe<b → c>, Maybe<b>) → Maybe<c>
    

    But this still requires you to be able to write Maybe<b → c> as the type of this, which is not possible in TypeScript afaik. Flow might get higher-kinded polymorphism at some point (facebook/flow#30) but it's not one of their priorities.

  • first-class tags (or some other kind of tagging/sums), basically the ability of overloading a method based on a static value, which is used by things like .matchWith, which call a function based on the tag an object has. Flow has had something like this since forever, TypeScript added this recently.

Some features use reflection or generate values. These could only be typed if we had a type system with dependent types (that is, your types are basically functions, so you can write things like sort : (Vector(len, x), (x, x -> Ord)) -> inTime(nlogn, Sorted(Vector(len, x))), which statically verifies that you've implemented a correct sort function that runs in n log n). Dependent types are still not practical.

Member

robotlolita commented Jan 17, 2017

Unlikely for now, the type system implemented by TypeScript (and Flow) are not expressive enough to support most of the constructs that Folktale uses, so you'd just end up with a lot of any types, which is not very useful. Folktale was not written for a particular type system, which makes this a bit difficult too (as the features require many advanced type system techniques).

Depending on how Flow and TypeScript advance in the future I might look into this again, though.

Right now Folktale requires at the very least three type system features:

  • Parametric polymorphism, the ability of writing a generic type over some parameters, and then specialising that later. Maybe<a>, Either<a, b>, etc. all require this. Both Flow and TypeScript support this (some people refer to them as "generics");

  • Higher-Kinded polymorphism, the ability of writing a generic type that you can pass around, and yield new types. Imagine the above, but Maybe is just as valid a usage as Maybe<a>, it just results in a "type function" where the thing you're passing the type to is supposed to provide the argument for Maybe to construct a type. This is required for monads and applicatives. The type of .apply is:

    apply :: forall a, b, c. (Applicative a) => (this: a<b → c>, a<b>) → a<c>
    

    The (Applicative a) => part just says "the type variable a is constrained to be an Applicative". Since we're using an object-oriented language we could just specialise this instead:

    apply :: forall b, c. (this: Maybe<b → c>, Maybe<b>) → Maybe<c>
    

    But this still requires you to be able to write Maybe<b → c> as the type of this, which is not possible in TypeScript afaik. Flow might get higher-kinded polymorphism at some point (facebook/flow#30) but it's not one of their priorities.

  • first-class tags (or some other kind of tagging/sums), basically the ability of overloading a method based on a static value, which is used by things like .matchWith, which call a function based on the tag an object has. Flow has had something like this since forever, TypeScript added this recently.

Some features use reflection or generate values. These could only be typed if we had a type system with dependent types (that is, your types are basically functions, so you can write things like sort : (Vector(len, x), (x, x -> Ord)) -> inTime(nlogn, Sorted(Vector(len, x))), which statically verifies that you've implemented a correct sort function that runs in n log n). Dependent types are still not practical.

@xaviervia

This comment has been minimized.

Show comment
Hide comment
@xaviervia

xaviervia Jan 17, 2017

Thanks for a great answer @robotlolita , I’ve been wondering the same thing as @djleonskennedy for a while, it’s good to have a complete explanation about this.

xaviervia commented Jan 17, 2017

Thanks for a great answer @robotlolita , I’ve been wondering the same thing as @djleonskennedy for a while, it’s good to have a complete explanation about this.

@djleonskennedy

This comment has been minimized.

Show comment
Hide comment
@djleonskennedy

djleonskennedy commented Jan 17, 2017

Understood thank you @robotlolita

@djleonskennedy

This comment has been minimized.

Show comment
Hide comment
@djleonskennedy

djleonskennedy Jan 18, 2017

Also have addition, even any typings would be handful, because now we can't use library with TS at all :(

djleonskennedy commented Jan 18, 2017

Also have addition, even any typings would be handful, because now we can't use library with TS at all :(

@AndriiDidkivsky

This comment has been minimized.

Show comment
Hide comment
@AndriiDidkivsky

AndriiDidkivsky commented Jan 18, 2017

I agree with @djleonskennedy

@robotlolita robotlolita reopened this Jan 18, 2017

@robotlolita

This comment has been minimized.

Show comment
Hide comment
@robotlolita

robotlolita Jan 18, 2017

Member

@djleonskennedy doesn't TypeScript infer any from things you haven't declared a type for, and then propagates that?

Member

robotlolita commented Jan 18, 2017

@djleonskennedy doesn't TypeScript infer any from things you haven't declared a type for, and then propagates that?

@djleonskennedy

This comment has been minimized.

Show comment
Hide comment
@djleonskennedy

djleonskennedy Jan 18, 2017

@robotlolita if implicit any flag is on, than we need typing's anyway :(

djleonskennedy commented Jan 18, 2017

@robotlolita if implicit any flag is on, than we need typing's anyway :(

@robotlolita

This comment has been minimized.

Show comment
Hide comment
@robotlolita

robotlolita Jan 19, 2017

Member

Mmh, I'll look into this over the weekend.

Member

robotlolita commented Jan 19, 2017

Mmh, I'll look into this over the weekend.

@djleonskennedy

This comment has been minimized.

Show comment
Hide comment
@djleonskennedy

djleonskennedy commented Jan 22, 2017

@robotlolita thank you

@robotlolita robotlolita added this to the v2.0.0 milestone Jan 29, 2017

@robotlolita robotlolita self-assigned this Feb 8, 2017

@piq9117

This comment has been minimized.

Show comment
Hide comment
@piq9117

piq9117 Feb 15, 2017

It's fine to use with typescript I'm just applying a band aid fix for now by declaring the module with any type just so I can use it with typescript.

declare module 'data.maybe' {
  const Maybe: any;
  export = Maybe;
}

piq9117 commented Feb 15, 2017

It's fine to use with typescript I'm just applying a band aid fix for now by declaring the module with any type just so I can use it with typescript.

declare module 'data.maybe' {
  const Maybe: any;
  export = Maybe;
}
@djleonskennedy

This comment has been minimized.

Show comment
Hide comment
@djleonskennedy

djleonskennedy Feb 23, 2017

@piq9117 thank you i use it now in this way

djleonskennedy commented Feb 23, 2017

@piq9117 thank you i use it now in this way

@OliverJAsh

This comment has been minimized.

Show comment
Hide comment
@OliverJAsh

OliverJAsh Apr 15, 2017

I hacked together some typings for use with the data.validation and data.maybe modules. The types should probably describe the underlying concepts such as Functor, Monad, but they are just hardcoded for now:

declare module 'data.maybe' {
    import Validation from 'data.validation';

    const Maybe: {
        fromValidation: <Success, Failure>(validation: Validation<Success, Failure>) => Maybe<Success>
        fromNullable: <T>(nullable: T | undefined | null) => Maybe<T>
        Just: <T>(t: T) => Maybe<T>
        of: <T>(t: T) => Maybe<T>
        Nothing: () => Maybe<never>
    }
    type Maybe<T> = {
        value: T
        getOrElse: (fallback: T) => T
        map: <T2>(fn: (t: T) => T2) => Maybe<T2>
        chain: <T2>(fn: (t: T) => Maybe<T2>) => Maybe<T2>
    }
    export default Maybe
}

// Applicative
declare module 'data.validation' {
    const Validation: {
        Success: <Success>(success: Success) => Validation<Success, never>
        of: <Success>(success: Success) => Validation<Success, never>
        Failure: <Failure>(failure: Failure) => Validation<never, Failure>
    }
    type Validation<Success, Failure> = {
        getOrElse: (fallback: Success) => Success
        map: <Success2>(fn: (success: Success) => Success2) => Validation<Success2, Failure>
        ap: (validation: Validation<any, any>) => Validation<any, any>
        cata: <T>(obj: {
            Success: (success: Success) => T,
            Failure: (failure: Failure) => T
        }) => T
    }
    export default Validation
}

I'm very much making it up as a go along. I've had to type Validation.ap as returning Validation<any,any>—would love help to fix this.

OliverJAsh commented Apr 15, 2017

I hacked together some typings for use with the data.validation and data.maybe modules. The types should probably describe the underlying concepts such as Functor, Monad, but they are just hardcoded for now:

declare module 'data.maybe' {
    import Validation from 'data.validation';

    const Maybe: {
        fromValidation: <Success, Failure>(validation: Validation<Success, Failure>) => Maybe<Success>
        fromNullable: <T>(nullable: T | undefined | null) => Maybe<T>
        Just: <T>(t: T) => Maybe<T>
        of: <T>(t: T) => Maybe<T>
        Nothing: () => Maybe<never>
    }
    type Maybe<T> = {
        value: T
        getOrElse: (fallback: T) => T
        map: <T2>(fn: (t: T) => T2) => Maybe<T2>
        chain: <T2>(fn: (t: T) => Maybe<T2>) => Maybe<T2>
    }
    export default Maybe
}

// Applicative
declare module 'data.validation' {
    const Validation: {
        Success: <Success>(success: Success) => Validation<Success, never>
        of: <Success>(success: Success) => Validation<Success, never>
        Failure: <Failure>(failure: Failure) => Validation<never, Failure>
    }
    type Validation<Success, Failure> = {
        getOrElse: (fallback: Success) => Success
        map: <Success2>(fn: (success: Success) => Success2) => Validation<Success2, Failure>
        ap: (validation: Validation<any, any>) => Validation<any, any>
        cata: <T>(obj: {
            Success: (success: Success) => T,
            Failure: (failure: Failure) => T
        }) => T
    }
    export default Validation
}

I'm very much making it up as a go along. I've had to type Validation.ap as returning Validation<any,any>—would love help to fix this.

@OliverJAsh

This comment has been minimized.

Show comment
Hide comment
@OliverJAsh

OliverJAsh Apr 15, 2017

Also, looking around for a good FP library with support for TypeScript and Fantasy Land, I don't think there's any really strong contenders at the moment. I would love to see Folktale emerge and fill this niche :-)

OliverJAsh commented Apr 15, 2017

Also, looking around for a good FP library with support for TypeScript and Fantasy Land, I don't think there's any really strong contenders at the moment. I would love to see Folktale emerge and fill this niche :-)

@robotlolita

This comment has been minimized.

Show comment
Hide comment
@robotlolita

robotlolita Apr 15, 2017

Member

@OliverJAsh With Microsoft/TypeScript#6739 you can probably write:

type Validation<S, F> = {
  ap: <S2>(this: Validation<Function<S, S2>, F>, validation: Validation<S, F>) => Validation<S2, F>
}

But I haven't tried it yet. I don't know if it's on the current TS version either.

Member

robotlolita commented Apr 15, 2017

@OliverJAsh With Microsoft/TypeScript#6739 you can probably write:

type Validation<S, F> = {
  ap: <S2>(this: Validation<Function<S, S2>, F>, validation: Validation<S, F>) => Validation<S2, F>
}

But I haven't tried it yet. I don't know if it's on the current TS version either.

@OliverJAsh

This comment has been minimized.

Show comment
Hide comment
@OliverJAsh

OliverJAsh commented Apr 15, 2017

Oh, wow! Thanks @robotlolita

@OliverJAsh

This comment has been minimized.

Show comment
Hide comment
@OliverJAsh

OliverJAsh commented Apr 15, 2017

@robotlolita That change is included in TS 2.3 which is currently out as a release candidate (RC): https://github.com/Microsoft/TypeScript/releases/tag/v2.3.0

@robotlolita robotlolita referenced this issue Apr 22, 2017

Open

Moving to TypeScript in 3.0 #115

1 of 4 tasks complete

@robotlolita robotlolita modified the milestones: 2.1.0, v2.0.0 Apr 22, 2017

@tmpethick

This comment has been minimized.

Show comment
Hide comment
@tmpethick

tmpethick Jun 4, 2017

Also, looking around for a good FP library with support for TypeScript and Fantasy Land, I don't think there's any really strong contenders at the moment. I would love to see Folktale emerge and fill this niche :-)

@OliverJAsh check out https://github.com/gcanti/fp-ts for ADT in TypeScript if you haven't already – the project seem to be moving fast.

tmpethick commented Jun 4, 2017

Also, looking around for a good FP library with support for TypeScript and Fantasy Land, I don't think there's any really strong contenders at the moment. I would love to see Folktale emerge and fill this niche :-)

@OliverJAsh check out https://github.com/gcanti/fp-ts for ADT in TypeScript if you haven't already – the project seem to be moving fast.

@xaviervia xaviervia referenced this issue Feb 21, 2018

Open

Add types #281

@robotlolita robotlolita removed this from the 2.1.0 milestone Jul 1, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment