optics-dev / optics-dev/Monocle
Macro expansion raises an error when type of field is written in long hand.
Nobody has claimed this yet.
- Dominant language
- Scala
- Stars
- 1.7k
- Forks
- 207
- Avg merge
- 7h 59m
- Merged PRs (30d)
- 5
Description
A Scastie is provided here...
Scala 3.3.4,
SBT includes Monocle dependency of:
libraryDependencies ++= Seq(
"dev.optics" %% "monocle-core" % "3.3.0",
"dev.optics" %% "monocle-macro" % "3.3.0"
)
import monocle.syntax.all.*
trait Algebra[Result[_], Element]:
def empty: Result[Element]
def addSomething(
partialResult: Result[Element],
newData: String
): Result[Element]
end Algebra
def weeklyGrind[Result[_], Element](
algebra: Algebra[Result, Element]
): Result[Element] =
val monday = algebra.empty
val tuesday = algebra.addSomething(monday, "A hard working day.")
// Long weekend follows...
tuesday
end weeklyGrind
type Steps[Element] =
Vector[[Result[Element]] => Algebra[Result, Element] => Result[
Element
] => Result[Element]]
// Polymorphic because we don't know what kind of result
// the downstream algebra will work with.
case class Recording[Element](steps: Vector[[Result[Element]] => Algebra[Result, Element] => Result[
Element
] => Result[Element]]):
// Changing to the commented out definition fixes the Monocle error...
/*case class Recording[Element](steps: Steps[Element]):*/
def playback[Result[Element]](
algebra: Algebra[Result, Element]
): Result[Element] =
steps.foldLeft(algebra.empty)((partialResult, step) =>
step(algebra)(partialResult)
)
class RecordingAlgebra[Element] extends Algebra[Recording, Element]:
def empty: Recording[Element] =
Recording(steps = Vector.empty)
def addSomething(
partialResult: Recording[Element],
newData: String
): Recording[Element] =
partialResult
.focus(_.steps)
.modify(
_.appended(
[Result[_]] =>
(downstreamAlgebra: Algebra[Result, Element]) =>
downstreamAlgebra.addSomething(_, newData)
)
)
end RecordingAlgebra
val onTheRecord = weeklyGrind(new RecordingAlgebra)
Note the alternative definition of Recording:
case class Recording[Element](steps: Vector[[Result[Element]] => Algebra[Result, Element] => Result[
Element
] => Result[Element]]):
// Changing to the commented out definition fixes the Monocle error...
/*case class Recording[Element](steps: Steps[Element]):*/
In the uncommented form, the macro expansion of the .focus(_.steps).modify(...) call in RecordingAlgebra fails with:
Exception occurred while executing macro expansion.
scala.quoted.runtime.impl.ExprCastException:
Expected type:
scala.collection.immutable.Vector[scala.PolyFunction {
val apply: [Result _ >: scala.Nothing <: [Element >: scala.Nothing <: scala.Any] => scala.Any](x$1: Playground.Algebra[Result, Recording.this.Element])scala.Function1[Result[Recording.this.Element], Result[Recording.this.Element]]
}]
Actual type: from.steps
Expression: from.steps
at scala.quoted.runtime.impl.ExprCastException$.apply(ExprCastException.scala:15)
at scala.quoted.runtime.impl.QuotesImpl.asExprOf(QuotesImpl.scala:75)
at scala.quoted.runtime.impl.QuotesImpl$reflect$TreeMethods$.asExprOf(QuotesImpl.scala:123)
at scala.quoted.runtime.impl.QuotesImpl$reflect$TreeMethods$.asExprOf(QuotesImpl.scala:122)
at monocle.internal.focus.features.selectonlyfield.SelectOnlyFieldGenerator.generateSelectOnlyField$$anonfun$1$$anonfun$1(SelectOnlyFieldGenerator.scala:24)
at monocle.internal.focus.features.selectonlyfield.SelectOnlyFieldGenerator.generateSelectOnlyField$$anonfun$1(SelectOnlyFieldGenerator.scala:24)
at monocle.internal.focus.features.selectonlyfield.SelectOnlyFieldGenerator.generateSelectOnlyField$$anonfun$adapted$1(SelectOnlyFieldGenerator.scala:25)
at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:110)
Using the commented form uses an equivalent type alias, and compiles correctly.
I'm not sure if this is down to Monocle, or is an issue with the Scala compiler itself.
The workaround is available (and looks better anyway), but I've raised this in case there is a deeper issue - but it's not urgent for me.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the Scastie example with Scala 3.3.4 and Monocle 3.3.0, focusing on the .focus(_.steps).modify(...) expansion. Start with monocle.internal.focus.features.selectonlyfield.SelectOnlyFieldGenerator.scala at the stack-trace location and compare the explicit field type with the Steps alias. Done means identifying whether the failure belongs to Monocle or the Scala compiler and adding a regression test or documented conclusion.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- scala
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100