folktale icon indicating copy to clipboard operation
folktale copied to clipboard

typescript typings

Open djleonskennedy opened this issue 9 years ago • 17 comments

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

djleonskennedy avatar Jan 17 '17 12:01 djleonskennedy

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 (https://github.com/facebook/flow/issues/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.

robotlolita avatar Jan 17 '17 13:01 robotlolita

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 avatar Jan 17 '17 14:01 xaviervia

Understood thank you @robotlolita

djleonskennedy avatar Jan 17 '17 15:01 djleonskennedy

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

djleonskennedy avatar Jan 18 '17 11:01 djleonskennedy

I agree with @djleonskennedy

AndriiDidkivsky avatar Jan 18 '17 11:01 AndriiDidkivsky

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

robotlolita avatar Jan 18 '17 13:01 robotlolita

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

djleonskennedy avatar Jan 18 '17 14:01 djleonskennedy

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

robotlolita avatar Jan 19 '17 02:01 robotlolita

@robotlolita thank you

djleonskennedy avatar Jan 22 '17 17:01 djleonskennedy

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 avatar Feb 15 '17 20:02 piq9117

@piq9117 thank you i use it now in this way

djleonskennedy avatar Feb 23 '17 15:02 djleonskennedy

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 avatar Apr 15 '17 16:04 OliverJAsh

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 avatar Apr 15 '17 16:04 OliverJAsh

@OliverJAsh With https://github.com/Microsoft/TypeScript/pull/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.

robotlolita avatar Apr 15 '17 20:04 robotlolita

Oh, wow! Thanks @robotlolita

OliverJAsh avatar Apr 15 '17 20:04 OliverJAsh

@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

OliverJAsh avatar Apr 15 '17 20:04 OliverJAsh

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 avatar Jun 04 '17 13:06 tmpethick