title: Implementing Either Monad in Typescript
body: <p>I've been experimenting with TypeScript lately, and I'm trying to implement some basic monads. I've already got a reasonably functioning Maybe (with the same methods of my Either below, at least), but Either is eluding me for type-related reasons I don't quite understand.</p>
  
  <p>My typing strategy for higher kinded types is borrowed from this article: <a href="https://medium.com/@gcanti/higher-kinded-types-in-typescript-static-and-fantasy-land-d41c361d0dbe" rel="noreferrer">https://medium.com/@gcanti/higher-kinded-types-in-typescript-static-and-fantasy-land-d41c361d0dbe</a>. I know there are libraries that already have all these monads and other FP goodies, but implementing them like this is my way of trying to learn TypeScript more deeply.</p>
  
  <pre><code>declare module './HKT' {
    interface TypeIDtoHKT2&lt;E, A&gt; {
      Either: Either&lt;E, A&gt;;
    }
  }
  
  export const TypeID = 'Either';
  export type TypeID = typeof TypeID;
  
  export class Left&lt;E&gt; {
    readonly _F!: TypeID;
    readonly _A!: E;
    readonly _tag: 'Left' = 'Left';
    constructor(readonly left: E) {}
    static of&lt;E, A&gt;(e: E): Either&lt;E, A&gt; {
      return new Left(e);
    }
    map&lt;A, B&gt;(f: (a: A) =&gt; B): Either&lt;E, B&gt; {
      return this;
    }
    chain&lt;A, B&gt;(f: (a: A) =&gt; Either&lt;A, B&gt;): Either&lt;E, B&gt; {
      return this;
    }
    ap&lt;A, B&gt;(f: Either&lt;A, (a: A) =&gt; B&gt;): Either&lt;E, B&gt; {
      return this;
    }
  }
  
  export class Right&lt;A&gt; {
    readonly _F!: TypeID;
    readonly _A!: A;
    readonly _tag: 'Right' = 'Right';
    constructor(readonly right: A) {}
    static of&lt;A, E&gt;(a: A): Either&lt;E, A&gt; {
      return new Right(a);
    }
    map&lt;E, B&gt;(f: (a: A) =&gt; B): Either&lt;E, B&gt; {
      return Right.of(f(this.right));
    }
    chain&lt;E, B&gt;(f: (a: A) =&gt; Either&lt;E, B&gt;): Either&lt;E, B&gt; {
      return f(this.right);
    }
    ap&lt;E, B&gt;(f: Either&lt;E, (a: A) =&gt; B&gt;): Either&lt;E, B&gt; {
      if (f instanceof Left) return f;
      return this.map(f.right);
    }
  }
  
  export type Either&lt;E, A&gt; = Left&lt;E&gt; | Right&lt;A&gt;;
  
  export const left = &lt;E, A&gt;(e: E): Either&lt;E, A&gt; =&gt; {
    return new Left(e);
  };
  
  export const right = &lt;E, A&gt;(a: A): Either&lt;E, A&gt; =&gt; {
    return new Right(a);
  };
  </code></pre>
  
  <p>When I try to run a test assertion, such as <code>right(4).map(isEven) === true</code>, I get the following error: </p>
  
  <p><code>Cannot invoke an expression whose type lacks a call signature. Type '(&lt;E, B&gt;(f: (a: number) =&gt; B) =&gt; Either&lt;E, B&gt;) | (&lt;A, B&gt;(f: (a: A) =&gt; B) =&gt; Either&lt;unknown, B&gt;)' has no compatible call signatures.</code></p>
  
  <p>I don't understand why the <code>E</code> type is <code>unknown</code> here or how I can make it known...or if that's even the right thing to be trying to do. Any guidance is appreciated.</p>