propensive / contextual

Statically-checked string interpolation in Scala
https://soundness.dev/contextual/
251 stars 23 forks source link

Offer type refinements on return types #67

Closed propensive closed 1 year ago

propensive commented 2 years ago

The return type of any Contextual value is fixed, but since the macro is transparent, it could be refined to a subtype. For example, in Guillotine the return type of a shell command such as sh"cat foo" could be typed as Command["cat"] instead of just Command. In this example, it would provide some further opportunities to have type inference automatically choose suitable return types for execution.

Known literal Text types from Gossamer could be refined to have the underlying String literal type available as a member.

This would probably be best provided through a mixin trait along the lines of:

trait Precision[State, Return]:
  interpolator: Interpolator[?, State, Return] =>
    type Refined[S <: String & Singleton] <: Return
    def result(state: State): String & Singleton

A user's implementation of result would provide the String based on the final State value which would be passed into the Refined type constructor to produce a new subtype of Return.

An alternative approach may be to change the Return type to Return[S <: String & Singleton] in all cases, and to provide a default implementation of result for users to override if they want this feature.

propensive commented 1 year ago

This may be achievable just by invoking the Contextual macro from another transparent inline macro, and applying the refinement.

propensive commented 1 year ago

This turns out to be completely possible without any special support from Contextual.