ts-plus / typescript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ideas for improving implicits

mikearnaldi opened this issue · comments

Treat function arguments as local implicit

This will cover most of the cases where you would otherwise specify an implicit local and avoids leaking in definition files, for example currently a common pattern would be:

function print<A>(a: A, /** @tsplus implicit local */ show: Show<A>) {
  const tuple = Derive<Show<[A,A]>>()
  return tuple.show([a,a])
}

And this if not removed (which we could support, i.e. not emitting local tags) would leak into the definition file (not a big deal). In any case it is kind of verbose.

With treating arguments as implicit the code would become:

function print<A>(a: A, show: Show<A>) {
  const tuple = Derive<Show<[A,A]>>()
  return tuple.show([a,a])
}

In the same direction we may want to consider all locals defined in a parent scope (source file included).

Potential drawbacks are that we may introduce perf issues but that may not be the case given the problem is scoped per-file and that the lookup is only triggered when derivation is triggered (i.e. compiling a file without a Derive won't be impacted at all).

Consider defined implicits for extensions

i.e. lookup each property of an implicit for things with a tsplus fluent/operator tag like;

interface Show<A> {
  /** @tsplus fluent object show */
  show(a: A): string
}
/** @tsplus implicit */
const showString: Show<string> = {
  show: s => `hello: ${s}`
}

"mike".show()

and:

interface Functor<F> {
  /** :tsplus fluent Kind map */
  map<A, B>(self: Kind<F, A>, f: (a: A) => B): B
}
/** @tsplus implicit */
declare const functorEither: Functor<EitherF>

Either.right(0).map(_ => `hello: ${_}`)

Closing for now as more research is needed on the topic