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

High Order Types #7435

Closed
DomBlack opened this issue Mar 8, 2016 · 8 comments
Closed

High Order Types #7435

DomBlack opened this issue Mar 8, 2016 · 8 comments
Labels
Duplicate An existing issue was already created Suggestion An idea for TypeScript

Comments

@DomBlack
Copy link

DomBlack commented Mar 8, 2016

Given the new this return type and F-bounded polymorphism I was a little surprised that I still could not express a functor interface

Example of Problem

interface IFunctor<A> {
  /** Maps `A` into `B` */
  map<B>(f: (a: A) => B): IFunctor<B>;
}

// A class with more than just IFunctor in it.
class Maybe<A> implements IFunctor<A> {
  constructor(init: A) { this.value = init; }
  isEmpty(): boolean { return false; }
  map<B>(f: (a: A) => B): IFunctor<B> { return new Maybe(f(this.value)); }
}

function toString<F extends IFunctor<any>>(a: F) { 
  return a.map((v: any) => '' + v); // no way to define that this returns F<string>
}

let a: Maybe<number> = new Maybe(100);
let b: Maybe<string> = toString(a);
// error TS2322: Type 'IFunctor<string>' is not assignable to type 'Maybe<string>'.

Ideal Solution:
Ideally we should be able to define that F needs to have a generic type, which we can change

interface IFunctor<A, F<A> extends IFunctor<> {
  /** Maps `A` into `B` */
  map<B>(f: (a: A) => B): F<B>;
}

or we can define the functions generics

function toString<A, F<A> extends IFunctor<A>>(a: F<A>): F<string> { ... }
@RyanCavanaugh
Copy link
Member

Can you fix up the repro so it produces the error you're describing (and no other errors)? I wrote this, trying to fill in the gaps:

interface IFunctor<A> {
  /** Maps `A` into `B` */
  map<B>(f: (a: A) => B): IFunctor<B>;
}

// Mark javascript arrays as Functor
declare interface Array<T> extends IFunctor<T> {}

// Create another functor like structure
class Maybe<A> implements IFunctor<A> {
    map<B>(f: (a: A) => B): IFunctor<B> { return undefined }
}

let a: Maybe<number>; // = Maybe.just(100)
let b: Maybe<string> = a.map((x) => '' + x) 

and didn't get an error

@DomBlack
Copy link
Author

DomBlack commented Mar 8, 2016

Hi Ryan, sorry about that - I've updated the example code which now throws an error at compile

@RyanCavanaugh
Copy link
Member

This (below) compiles. You put an explicit type annotation on Maybe#map that said it returned a less-specific type, then tried to convert that to a more-specific type on the final line -- the compiler can't know that that's safe.

interface IFunctor<A> {
  /** Maps `A` into `B` */
  map<B>(f: (a: A) => B): IFunctor<B>;
}

// Mark javascript arrays as Functor
declare interface Array<T> extends IFunctor<T> {}

// A class with more than just IFunctor in it.
class Maybe<A> implements IFunctor<A> {
  value: A;
  constructor(init: A) { this.value = init; }
  isEmpty(): boolean { return false; }
  map<B>(f: (a: A) => B) { return new Maybe(f(this.value)); }
}

let a: Maybe<number> = new Maybe(100);
let b: Maybe<string> = a.map((x: number) => '' + x);

@mhegazy
Copy link
Contributor

mhegazy commented Mar 8, 2016

duplicate of #5999?

@zpdDG4gta8XKpMCd
Copy link

dupe of #1213 (although the title of it is sort of strange) a bit of a rant @RyanCavanaugh's been giving some tough love there, how many people do you guys know who can go into your code base and outline how HKT would look like right there in code? 3? 4?

@RyanCavanaugh
Copy link
Member

how many people do you guys know who can go into your code base and outline how HKT would look like right there in code? 3? 4?

Correct (if not fewer). The scarcity of such resources is exactly the source of its current prioritization. We have a large number of features that can only be done correctly by a few experts, so it's important that those people are working on the features with the highest value. No one's saying it wouldn't be a cool thing to have (I ❤️ FP features too), but it addresses fewer scenarios than other things currently in the pipe.

@DomBlack
Copy link
Author

DomBlack commented Mar 8, 2016

Sorry I was trying to make a simple example of what I've been trying to do and missed a key point.

I've updated the example code again, trying to show a failure which I can't see how to get around without high order types.

#1213 is very similar but takes a different approach to the issue (separate classes for the monads, rather than building it into the classes directly).

For us it's not a priority as we've worked around it, but would be nice to have in the future

@mhegazy
Copy link
Contributor

mhegazy commented Mar 28, 2016

closing in favor of #1213

@mhegazy mhegazy closed this as completed Mar 28, 2016
@mhegazy mhegazy added Suggestion An idea for TypeScript Duplicate An existing issue was already created labels Mar 28, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants