Skip to content
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
Open

typescript typings #65

djleonskennedy opened this issue Jan 17, 2017 · 17 comments

Comments

@djleonskennedy
Copy link

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

@robotlolita
Copy link
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 (Support higher kinded type 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
Copy link

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
Copy link
Author

Understood thank you @robotlolita

@djleonskennedy
Copy link
Author

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
Copy link

AndriiDidkivsky commented Jan 18, 2017

I agree with @djleonskennedy

@robotlolita robotlolita reopened this Jan 18, 2017
@robotlolita
Copy link
Member

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

@djleonskennedy
Copy link
Author

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

@robotlolita
Copy link
Member

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

@djleonskennedy
Copy link
Author

@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
Copy link

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
Copy link
Author

@piq9117 thank you i use it now in this way

@OliverJAsh
Copy link

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
Copy link

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
Copy link
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
Copy link

Oh, wow! Thanks @robotlolita

@OliverJAsh
Copy link

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

@tmpethick
Copy link

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.

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

No branches or pull requests

7 participants