evilsoft / crocks

A collection of well known Algebraic Data Types for your utter enjoyment.
https://crocks.dev
ISC License
1.59k stars 102 forks source link

TS typings #286

Open tonisostrat opened 6 years ago

tonisostrat commented 6 years ago

Have you planned or thought about creating typings files to support us TS developers?

evilsoft commented 6 years ago

I have given it a lot of thought and will not support either TS or flow types officially. But if anyone makes and maintains them, I will gladly link to those libs.

EDIT: crocks is intended to be a Javascript lib, I think there are many other libs out there that do support TS and flow out of the box.

evilsoft commented 6 years ago

But out of curiosity, if you have any experience in building typings for ADTs...what would this translate to in T$?

https://github.com/evilsoft/crocks/blob/master/src/Pred/index.js

EDIT: it is a Monoidal Contravarient functor that wraps a Predicate function that goes from anytype a to Boolean.... So a Pred a Boolean. you can change it to another (or same type) b by using contramap that takes a function b -> a, making it a Pred b Boolean

tonisostrat commented 6 years ago

Unfortunately I'm the wrong person to ask as I don't have enough experience in writing complex typing files, somebody a lot smarter has to tackle this one.

EDIT:

I think this is a good example of typings that support mapping functions like a -> b where both can be random types, etc.

evilsoft commented 6 years ago

Bummer sauce. Well if anyone ends up making typings for these Types and Functions, I will def throw a link in the docs and give you a shout out.

karthikiyengar commented 6 years ago

@evilsoft - Here are some typings for Pred. I haven't really spent time on further enhancing this, but as it stands the compile-time checks and intellisense are promising.

type PredFn = (a: any) => boolean;
type TransformFn = (a: any) => any;

type Instance = {
    runWith: (a) => boolean,
    inspect: () => string, 
    toString: () => string,
    concat: (a: Instance) => Instance,
    empty: () => Instance,
    contramap: (a: TransformFn) => Instance,
}

declare var Pred: {
    (a: PredFn): Instance
    empty: () => Instance
    type: () => string
}

export = Pred;
evilsoft commented 6 years ago

Hmmm. okay. this is not as bad. @karthikiyengar could you try Identity. Maybe this is something we can do. @karthikiyengar @dalefrancis88 and @bennypowers and whoever.

What do you think about us doing this? For just the types?

karthikiyengar commented 6 years ago

@evilsoft - I think the biggest win from this would be the ease of API exploration and avoiding a large number of instantiation/usage errors.

If the above example (and our PoC with Identity - I'll put it up soon) is anything to go by, we can have excellent type support for the crocks and monoids - the red squiggly lines makes me feel warm and fuzzy.

Pointfree functions are going to be a bit painful, and we will start hitting T$'s limitations. That being said, it is completely possible to type a boatload of functions we provide similar to Ramda (although they default to any a lot, it still kind of works). And it does look like things are going to improve with https://github.com/Microsoft/TypeScript/pull/24897 - which will be released soon.

evilsoft commented 6 years ago

Well. Then with this being the fourth person asking, I think it is time we seriously explore this option.

karthikiyengar commented 6 years ago

@evilsoft - I've setup some types and tests for Identity at https://github.com/karthikiyengar/crocks-types - could you please take a look? Failing tests are sections where the types can be improved - I'm afraid I don't have the smarts at the moment to do better. The lack of Higher Kinded Types makes things difficult.

Notable resources: https://gcanti.github.io/fp-ts - Looks like applicatives are partially working for them https://github.com/gcanti/fp-ts/blob/master/HKT.md - An excellent article on how to emulate HKTs. https://github.com/SimonMeskens/TypeProps - Another approach. https://github.com/cbowdon/TsMonad - Can draw inspiration from here https://www.cl.cam.ac.uk/~jdy22/papers/lightweight-higher-kinded-polymorphism.pdf - I can't bring myself to read this just yet. https://github.com/Microsoft/TypeScript/issues/1213 - T$ proposal for HKT

evilsoft commented 6 years ago

@karthikiyengar amazing. looks like I will be learning me some T$. (don't tell the people I work with tho, they will make so much fun of me)

rpearce commented 6 years ago

^ that's not true! Tell us of your learnings. I've done some TS courses on egghead and am impressed by some bits of it.

bennypowers commented 6 years ago

FYI jsdoc comments will work with TS editor plugins

And es modules (which I haven't forgotten about) will help with static analysis.

karthikiyengar commented 6 years ago

I'd be super happy to kick things off on this one. I'm assuming that we aren't considering a full-fledged move to TS when it comes to the library itself. That leaves us with two options.

  1. Include d.ts definitions as a part of the library. This allows us to have autonomy over lint-rules, tests etc.
  2. Fork DefinitelyTyped and PR crocks typedefs.

If we could decide on the approach, we can calculate next steps.

zdrr commented 6 years ago

https://github.com/Microsoft/dts-gen can generate the starting template and you can build up from there. I'm heavily interested in this as well and would like to contribute when I can. TS is no bullshit, you'll appreciate the cognitive de-load once you start using all the tooling surrounding it.

I think, the last frontier for TS is this: https://github.com/Microsoft/TypeScript/issues/5453 (most of the primitives are already implemented), with that done TS will fully encompass the strongly typed fp/frp in js.

kjellmorten commented 6 years ago

Thanks for looking into this!

I'd like to give a +1 for including a d.ts definition in the library (option 1 from @karthikiyengar) as this will make crocks support TS "out of the box".

DefinitelyTyped is great, but is more of a fix for libraries that does not support TS.

karthikiyengar commented 6 years ago

If @evilsoft can give us a go ahead on this one, I'd be happy to kick-start a PR!

On Sat, Aug 4, 2018, 12:19 PM Kjell-Morten notifications@github.com wrote:

Thanks for looking into this!

I'd like to give a +1 for including a d.ts definition in the library (option 1 from @karthikiyengar https://github.com/karthikiyengar) as this will make crocks support TS "out of the box".

DefinitelyTyped is great, but is more of a fix for libraries that does not support TS.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/evilsoft/crocks/issues/286#issuecomment-410439226, or mute the thread https://github.com/notifications/unsubscribe-auth/AH4Kb5AMLGdDFvkdZ-8AMJZaAtDW74Fyks5uNXUvgaJpZM4U4nze .

evilsoft commented 6 years ago

@kjellmorten I would much prefer it not being in the lib, this is a Javascript, not a T$ lib as such I would only :corn:sider adding on these conditions:

While as @zdrr stated, T$ is not bull-poop, I really do not think it is ready for actual Functional Programming without removing the power that Javascript has to offer in the functional space. All of the code I have seen using T$ the way you can use Javascript functionally requires a lot of specialization and compromises to things that are super simple in JS. That specialization (that I have seen) leads to many brittle definitions in the application domain.

Once those (4) conditions are met, then I am okay with it being officially supported in the lib, otherwise I am okay someone adding them to that typings repo, with the understanding that under no circumstance will any code be modified to accommodate those typings. I have seen a couple really good ADT libs lose so much power to accommodate T$ and I would rather not degrade crocks the same way.

My hope is, that as a functional community we stop trying to make something that was built for Object Oriented Programming work in a functional paradigm, and focus on something that works for functional javascript.

[end "make people angry" rant]

evilsoft commented 6 years ago

All that said tho, @karthikiyengar if we can hit those (4) things, I will happily merge it in.

karthikiyengar commented 6 years ago

@evilsoft - Roger. It's easily possible to achieve 1 and 3 at the moment. Typescript has some really kick-ass support for discriminated unions.

With regards to 2 and 4, I think there's been some progress made in the 3.0 release. Allow me to perform some experiments before I get back to you on this one.

eddiemoore commented 6 years ago

There is an open issue for Variadic Kinds in the TypeScript https://github.com/Microsoft/TypeScript/issues/5453 It's currently listed under the "Future" for the TS roadmap https://github.com/Microsoft/TypeScript/wiki/Roadmap However things like curried functions is still possible, just a little verbose in the definition file.

evilsoft commented 6 years ago

@eddiemoore that is great news! So by verbose, do you mean for a ternary function would that mean accounting for

Also without knowing what compose means is it able to capture the composition for the function we provide here or would we have to change that to accommodate?

evilsoft commented 6 years ago

@karthikiyengar just looked into the union types for T$. That is pretty awesome!

eddiemoore commented 6 years ago

@evilsoft Yeah, so you can define overloads in TypeScript if a function can take different params in different ways. It's a little annoying at the moment having to write it out 4 times, however it does give you the nice code hints and type safety plus more.

As for compose, not sure if this is the best way or not, but it seems to work:

function compose<A>(fn: (...x: any[]) => A, ...fns: Array<(...y: any[]) => any>): A

// use:
const x = compose(() => 42) // type of x will be a number
const y = compose(() => 'something', () => 42) // type of y will be a string

~So will always return the return type of the first param, and then the other arguments would be an array of functions that may return any type. Also allowing for the functions that are passed in to take any amount of parameters. Something along these lines would work.~

Update: Ignore the compose stuff.... I realise it's wrong lol.

eddiemoore commented 6 years ago

Ok better way is probably to use the overloads:

export type Arity1<A, B> = (a: A) => B;

export function compose<A, B>(f: Arity1<A, B>): Arity1<A, B>;
export function compose<A, B, C> (g: Arity1<B, C>, f: Arity1<A, B>): Arity1<A, C>;
export function compose<A, B, C, D> (h: Arity1<C, D>, g: Arity1<B, C>, f: Arity1<A, B>): Arity1<A, D>;
export function compose<A, B, C, D, E> (i: Arity1<D, E>, h: Arity1<C, D>, g: Arity1<B, C>, f: Arity1<A, B>): Arity1<A, E>;
export function compose<A, B, C, D, E, F> (j: Arity1<E, F>, i: Arity1<D, E>, h: Arity1<C, D>, g: Arity1<B, C>, f: Arity1<A, B>): Arity1<A, F>;

source: https://github.com/TylorS/typed-compose/blob/master/src/compose.ts

karthikiyengar commented 6 years ago

@eddiemoore - Great! Libs like ramda use some form of codegen to minimize manual typing for compose/curry. I was wondering if you think https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#generic-rest-parameters (or other new 3.0 features) helps in typing curry/compose.

I've been trying to wrap my mind around it, but I've run into a dead end.

An interesting thread here: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/27715#thread-subscription-status

eddiemoore commented 6 years ago

@karthikiyengar it might help. Haven't dug into it enough though.

evilsoft commented 6 years ago

The only problem with the overloads, is that unlike ramda, we do not stop at 10. you can make a composition as big as you need.

karthikiyengar commented 6 years ago

@evilsoft - Sure, you can extend it via codegen to an arity of n, but it comes with a performance cost AFAIK.

https://github.com/types/npm-ramda/blob/master/templates/compose.ts

On Fri, Aug 10, 2018, 7:22 PM Ian Hofmann-Hicks notifications@github.com wrote:

The only problem with the overloads, is that unlike ramda, we do not stop at 10. you can make a composition as big as you need.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/evilsoft/crocks/issues/286#issuecomment-412149498, or mute the thread https://github.com/notifications/unsubscribe-auth/AH4Kb5jgY7LgI5NnbSEPqqJBM74Z69j6ks5uPcFbgaJpZM4U4nze .

karthikiyengar commented 6 years ago

Spent some time digging deeper into this. Here's some stuff that I've uncovered.

  1. We need to decide if the typings are going to be a separate repository (like https://github.com/types/npm-ramda/) or be a part of the crocks main codebase. There are arguments for and against this.
  2. https://github.com/ikatyang/dts-element-fp does a great job of code-generating definitions for curry/compose.
  3. Since we'd have to rely on codegen, we have to set up some serious infrastructure that allows us to develop and test the final .d.ts file to template and interpolate the final module declaration.

I'd really appreciate direction from someone more experienced with this than myself, although I'm willing to put the time in.

@ikatyang - Could you please share some of your thoughts about this with us?

ikatyang commented 6 years ago
  1. Declaration files shouldn't be placed in non-TS projects, placing the declaration files in the main repo means it should be responsible for it, that is, you may have to release a new version just because of the TS declaration bugfixes, and if there're PRs for new functions or something, you can't ask people to write declaration for it since this is a JS project, which means it's easy to be out of sync.
  2. It should be fine to use it, though I didn't document it well.
  3. It should be just a matter to setup the codegen and dts-jest, the complexity in npm-ramda is just because I'd like to use them in the watch mode and a lot of custom usage to suit the ramda case.
karthikiyengar commented 6 years ago

Many thanks for your inputs @ikatyang

After conversations with @evilsoft, it appears that considering the direction that the library is moving, certain aspects of the library would be impossible to type.

At the moment, I'm not entirely sold that this is the best use of our time given the limited value that it adds.

However, https://github.com/karthikiyengar/crocks-types provides a quick boilerplate if anyone wants to experiment with definitions. It has dev and test scripts setup already, with a couple of mock types.

evilsoft commented 6 years ago

With the direction that crocks will be going I am closing this out for now. At its core, crocks is a JavaScript library and with the direction we are going we are moving further away from easy implementation in languages like TS.

ivosabev commented 5 years ago

Although I prefer crocks to its alternative (https://github.com/gcanti/fp-ts) the lack of TS typings is a bit problematic. I understand there are limitations in TS that prevent from proper typing of everything, but isn't there a compromise solution that could help this library integrate better with TS projects? I think this is a direction worth exploring as I am sure there are a lot of other people wanting to use crock but being put off by the lack of TS support.

evilsoft commented 5 years ago

@ivosabev Sorry about the problems the lack of typings create for you. Another thing to consider is that this is first and foremost a JavaScript library for JavaScript. Personally I do not have a need or desire to use and learn TypeScript, which I would have to do to be able to properly support the library. So then it becomes a lack of resource as well.

If I were to venture out of JavaScript for an alternative language (not for crocks, but just another language that compiles to JS) I would personally go for PureScript. I get full typings there and it is made for functional programming.

On top of that I would hate to add the cost and end up with strange intermediary functions or any all over the place. Does not seem like a lot of benefit from the cost of supporting another language that is not JS.

I am open to suggestion for some compromise to allow for better integration, but do not have the will or resources to convert the entire lib. If someone want to fork it for those folks that use TS, I would help promote such forks.

jakubbarczyk commented 4 years ago

@evilsoft I have started working on a @types/crocks typings. First draft is going to be pretty basic. I'm not going to write insane generics or anything like that. Let me share my work with all crocks enthusiasts later this month. Have a good one!

dalefrancis88 commented 4 years ago

I'll be excited to see the result of this. A few people have tried it and all hit the same realization but potentially with the recent changes to typescript to better handle fp concepts maybe this may be something that's worthwhile

jakubbarczyk commented 4 years ago

Sorry for the delay. I've just pushed some initial changes here. As mentioned above, I didn't care for generics. There's a number of duplicate lines for common methods, such as map, concat, ap, etc. As soon as the first draft is completed, I'm going to extract some helper types to improve maintainability of the lib. There are plenty of point-free and combinator functions to address. I'm getting there...

dalefrancis88 commented 4 years ago

Nice, i'll check it out. Do you want feedback or is this more of a heads up?

jakubbarczyk commented 4 years ago

It's more of a heads up, however all comments are very welcome! My primary objective at the moment is to push those clunky definitions out to allow for some Intellisense and auto-imports.

Also, I noticed that documentation page for List, Star and probably Writer is missing from here. Could someone update the docs? It would help me immensely in writing the definitions if I had those laid out.

dalefrancis88 commented 4 years ago

We're holding off on writing the docs for List atm as their is a big refactor for it coming up, Writer was started by @karthikiyengar and you can see that here if you want some docs, https://github.com/evilsoft/crocks/blob/writer-docs/docs/src/pages/docs/crocks/Writer.md

I'm not sure when Star's docs will be written

bennypowers commented 4 years ago

I'm reopening this as we have consensus that this is a good thing.

@jakubbarczyk is there anything I can do to help you along?

jakubbarczyk commented 4 years ago

@bennypowers I could use some documentation update, as mentioned here:

I noticed that documentation page for List, Star and probably Writer is missing from here. Could someone update the docs? It would help me immensely in writing the definitions if I had those laid out.

Aside from that, I should be able to finalize the initial draft this week.

karthikiyengar commented 4 years ago

@jakubbarczyk - I'll be done with Writer by the end of this week!

bennypowers commented 4 years ago

@jakubbarczyk I had a few ideas for this project, resulting from testing it out on a project i'm working on

If you like, I can send in a PR or we can maybe schedule a pair programming session, LMK

jakubbarczyk commented 4 years ago

@bennypowers sure, go ahead. I am up for that.

bennypowers commented 4 years ago

I'll send a PR to your branch sometime today, with comments about some of the changes in the PR description

jakubbarczyk commented 4 years ago

@bennypowers I'm thinking of writing generic interfaces for things like Monoid, Semigroup, etc. and have the type-classes implement them. I imagine including those interfaces in the internal directory. That could help with maintainability and reusability in the long run.

bennypowers commented 4 years ago

my interest in generics was mainly around helpers, tbh

dalefrancis88 commented 4 years ago

I can add context that I believe it unlikely that any typescript will make it's way into the main project. @evilsoft as well as myself are of the opinion that keeping this as a JS library only is the best option. I don't mean to speak for @evilsoft, just more to share what he's previously said around typescript and other similiar ideas. That being said contrib libraries are always encouraged and supported

dalefrancis88 commented 4 years ago

When you guys do your pair session it'd be great to hear what comes out of it. I'm following this closely because TS is a new thing coming in on my team and i'm actually using this PR as a way to get people more excited on FP and crocks