Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/makkarpov/explicits
A tiny library to have more control over Scala 3 implicit resolution in macros
https://github.com/makkarpov/explicits
scala scala-3 scala-macros
Last synced: 6 days ago
JSON representation
A tiny library to have more control over Scala 3 implicit resolution in macros
- Host: GitHub
- URL: https://github.com/makkarpov/explicits
- Owner: makkarpov
- License: apache-2.0
- Created: 2023-11-25T15:02:39.000Z (12 months ago)
- Default Branch: master
- Last Pushed: 2024-08-12T16:03:13.000Z (3 months ago)
- Last Synced: 2024-08-12T18:34:16.767Z (3 months ago)
- Topics: scala, scala-3, scala-macros
- Language: Scala
- Homepage:
- Size: 22.5 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
explicits
=========A tiny library which gives macro authors much more control over Scala 3 implicit resolution process.
```scala
libraryDependencies += "mx.m-k" %% "explicits" % "0.1"
```Implicit resolution
-------------------Vanilla `Implicits.search` method provided by the compiler has several major drawbacks:
* It resolves implicits strictly in the scope of a macro application: you cannot inject any additional imports or givens even if you know where to look,
* and it either resolves the implicit completely or completely fails. You cannot get half-resolved result like "I can do that, but you need to provide X and Y for me".Second drawback is critical if you are writing a macros to derive typeclasses recursively. Consider the following example:
```scala
trait CanMeow[T] { /* ... */ }given seqCanMeow[T](using CanMeow[T]): CanMeow[Seq[T]] = ???
case class Foo(/* ... */)
case class Bar(foos: Seq[Foo]) derives CanMeow
```In this case, you will never resolve `seqCanMeow` implicit with default API. This library could provide you a half-completed result saying "give me a `CanMeow[Foo]` and I will build `CanMeow[Seq[Foo]]` for you".
Usage example
-------------All magic starts with `ImplicitSearch.builder` method:
```scala
import mx.mk.explicits.{ImplicitSearch, Symbol}def deriveMeow[T](using Type[T], Quotes): Expr[CanMeow[T]] = {
val r = ImplicitSearch.builder[T]
// inject additional imports:
.extraLocations(Symbol.forModule("com.example.MeowModule"))
// provide explicit givens:
.give[CanMeow[Foobar]]('{ ??? })
// setup the assisted resolution:
.assist {
case '[ CanMeow[t] ] => true // sure, everything can meow with me
case _ => false // can't assist with anything else
}
.search() // get the final result
.toSuccess // aborts the macro if search failed
// inspect and derive what was missing:
val meows: Seq[Expr[?]] = success
.missingTypes
.map {
case '[ CanMeow[t] ] =>
'{ new CanMeow[t] { /* teach `t` to meow here */ } }
}
// construct the final expression:
success.construct(meows)
}
```If you don't use the `.assist()` method, `ImplicitSearch.Success` will always have `missingTypes` field empty, and simple `.construct(Nil)` is sufficient to get the final expression. Any missing implicit will fail the overall resolution process if assisted resolution is disabled.
If you want to assist the compiler with implicit resolution:
1. `.assist()` method takes a type filter predicate (`Type[?] => Boolean`). This predicate should test whether a value for the type could be generated by your code. Search will fail if it encounters a missing value which fails the test.
2. You should inspect `.missingTypes` field of the search result and provide expressions for all types listed there. Final expression is then constructed from the provided parts by the `.construct()` method.Compatibility
-------------Since this library heavily depends on the compiler internals, it could easily break even on slightest compiler change. To ensure seamless operation across a wide range of compiler versions, this library internally packs multiple backend implementations and selects a correct one at runtime.
Currently, this library is tested to work on all released compiler versions from **3.2.0** up to **3.4.2**.
License
-------This library is licensed under Apache 2.0 license.