optics-dev / Monocle

Optics library for Scala

Home Page:https://www.optics.dev/Monocle/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MatchError using `as` inside Focus

kenbot opened this issue · comments

Playing with this codebase: https://github.com/bblfish/lens-play/blob/master/src/main/scala/server/Server.scala

sbt> console
scala> import monocle.syntax.all._; import server._; import Server._
scala> val container = Container(Map("foo" -> Container(Map("bar" -> TextResource("banana")))))
val container: server.Server.Container = Container(Map(foo -> Container(Map(bar -> TextResource(banana,2021-09-01T13:29:42.917567400Z)),2021-09-01T13:29:42.917567400Z)),2021-09-01T13:29:42.917567400Z)

// External as works:
scala> container.focus(_.index(List("foo", "bar"))).as[TextResource].getOption
val res2: Option[server.Server.TextResource] = Some(TextResource(banana,2021-09-01T13:29:42.917567400Z))

// Internal as fails:
scala> container.focus(_.index(List("foo", "bar")).as[TextResource]).getOption
1 |container.focus(_.index(List("foo", "bar")).as[TextResource]).getOption
  |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |Exception occurred while executing macro expansion.
  |scala.MatchError: Skolem(1798376932) (of class dotty.tools.dotc.core.Types$SkolemType)
  |     at scala.quoted.runtime.impl.printers.Extractors$ExtractorsPrinter.visitType(Extractors.scala:233)
  |     at scala.quoted.runtime.impl.printers.Extractors$.showType(Extractors.scala:12)
  |     at scala.quoted.runtime.impl.QuotesImpl$$anon$17.show(QuotesImpl.scala:2898)
  |     at scala.quoted.runtime.impl.QuotesImpl$$anon$17.show(QuotesImpl.scala:2897)
  |     at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeReprMethods$.show(QuotesImpl.scala:1660)
  |     at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeReprMethods$.show(QuotesImpl.scala:1660)
  |     at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType(SourceCode.scala:1228)
  |     at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType(SourceCode.scala:1102)
  |     at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printSeparated$9(SourceCode.scala:730)
  |     at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printTypesOrBounds(SourceCode.scala:736)
  |     at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType$$anonfun$2(SourceCode.scala:1137)
  |     at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.inSquare(SourceCode.scala:88)
  |     at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType(SourceCode.scala:1137)
  |     at scala.quoted.runtime.impl.printers.SourceCode$.showType(SourceCode.scala:13)
  |     at scala.quoted.runtime.impl.QuotesImpl$$anon$14.show(QuotesImpl.scala:2886)
  |     at scala.quoted.runtime.impl.QuotesImpl$$anon$14.show(QuotesImpl.scala:2885)
  |     at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeReprMethods$.show(QuotesImpl.scala:1660)
  |     at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeReprMethods$.show(QuotesImpl.scala:1660)
  |     at monocle.internal.focus.features.as.AsParser$KeywordAs$.unapply(AsParser.scala:17)
  |     at monocle.internal.focus.features.ParserLoop.loop$1(ParserLoop.scala:50)
  |     at monocle.internal.focus.features.ParserLoop.parseFocusActions(ParserLoop.scala:64)
  |     at monocle.internal.focus.features.ParserLoop.parseFocusActions$(ParserLoop.scala:27)
  |     at monocle.internal.focus.FocusImpl.parseFocusActions(FocusImpl.scala:7)
  |     at monocle.internal.focus.FocusImpl.$anonfun$1(FocusImpl.scala:20)
  |     at scala.util.Either.flatMap(Either.scala:352)
  |     at monocle.internal.focus.FocusImpl.run(FocusImpl.scala:22)
  |     at monocle.internal.focus.FocusImpl$.apply(FocusImpl.scala:33)
  |     at monocle.internal.focus.AppliedFocusImpl$.apply(AppliedFocusImpl.scala:13)
  |
  | This location contains code that was inlined from rs$line$10:1

Here's another one, this time from an index call:

val i = summon[Index[Resource[?], List[String], Resource[?]]]
server.focus(_.index(path)(using i))
Exception occurred while executing macro expansion.
scala.MatchError: Skolem(165252930) (of class dotty.tools.dotc.core.Types$SkolemType)
	at scala.quoted.runtime.impl.printers.Extractors$ExtractorsPrinter.visitType(Extractors.scala:233)
	at scala.quoted.runtime.impl.printers.Extractors$.showType(Extractors.scala:12)
	at scala.quoted.runtime.impl.QuotesImpl$$anon$17.show(QuotesImpl.scala:2898)
	at scala.quoted.runtime.impl.QuotesImpl$$anon$17.show(QuotesImpl.scala:2897)
	at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeReprMethods$.show(QuotesImpl.scala:1660)
	at scala.quoted.runtime.impl.QuotesImpl$reflect$TypeReprMethods$.show(QuotesImpl.scala:1660)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType(SourceCode.scala:1228)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType(SourceCode.scala:1102)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printSeparated$9(SourceCode.scala:730)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printTypesOrBounds(SourceCode.scala:736)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType$$anonfun$2(SourceCode.scala:1137)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.inSquare(SourceCode.scala:88)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType(SourceCode.scala:1137)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printSeparated$9(SourceCode.scala:732)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printTypesOrBounds(SourceCode.scala:736)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType$$anonfun$2(SourceCode.scala:1137)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.inSquare(SourceCode.scala:88)
	at scala.quoted.runtime.impl.printers.SourceCode$SourceCodePrinter.printType(SourceCode.scala:1137)
	at scala.quoted.runtime.impl.printers.SourceCode$.showType(SourceCode.scala:13)
	at scala.quoted.runtime.impl.QuotesImpl$$anon$14.show(QuotesImpl.scala:2886)
	at scala.quoted.runtime.impl.QuotesImpl$$anon$14.show(QuotesImpl.scala:2885)
	at scala.quoted.runtime.impl.QuotesImpl.asExprOf(QuotesImpl.scala:71)
	at scala.quoted.runtime.impl.QuotesImpl$reflect$TreeMethods$.asExprOf(QuotesImpl.scala:113)
	at scala.quoted.runtime.impl.QuotesImpl$reflect$TreeMethods$.asExprOf(QuotesImpl.scala:112)
	at monocle.internal.focus.features.index.IndexGenerator.generateIndex$$anonfun$4(IndexGenerator.scala:15)
	at monocle.internal.focus.features.index.IndexGenerator.generateIndex$$anonfun$adapted$2(IndexGenerator.scala:15)
	at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:82)
	at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1367)
	at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:107)
	at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:97)
	at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1333)
	at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:107)
	at dotty.tools.dotc.quoted.PickledQuotes$.spliceTerms(PickledQuotes.scala:122)
	at dotty.tools.dotc.quoted.PickledQuotes$.unpickleTerm(PickledQuotes.scala:61)
	at scala.quoted.runtime.impl.QuotesImpl.unpickleExpr(QuotesImpl.scala:2913)
	at monocle.internal.focus.features.index.IndexGenerator.generateIndex(IndexGenerator.scala:15)
	at monocle.internal.focus.features.index.IndexGenerator.generateIndex$(IndexGenerator.scala:6)
	at monocle.internal.focus.FocusImpl.generateIndex(FocusImpl.scala:7)
	at monocle.internal.focus.features.GeneratorLoop.generateActionCode(GeneratorLoop.scala:48)
	at monocle.internal.focus.features.GeneratorLoop.generateCode$$anonfun$2$$anonfun$1(GeneratorLoop.scala:36)
	at scala.util.Either.flatMap(Either.scala:352)
	at monocle.internal.focus.features.GeneratorLoop.generateCode$$anonfun$1(GeneratorLoop.scala:36)
	at scala.collection.LinearSeqOps.foldLeft(LinearSeq.scala:169)
	at scala.collection.LinearSeqOps.foldLeft$(LinearSeq.scala:165)
	at scala.collection.immutable.List.foldLeft(List.scala:79)
	at monocle.internal.focus.features.GeneratorLoop.generateCode(GeneratorLoop.scala:36)
	at monocle.internal.focus.features.GeneratorLoop.generateCode$(GeneratorLoop.scala:27)
	at monocle.internal.focus.FocusImpl.generateCode(FocusImpl.scala:7)
	at monocle.internal.focus.FocusImpl.$anonfun$3$$anonfun$2(FocusImpl.scala:21)
	at scala.util.Either.flatMap(Either.scala:352)
	at monocle.internal.focus.FocusImpl.$anonfun$1(FocusImpl.scala:22)
	at scala.util.Either.flatMap(Either.scala:352)
	at monocle.internal.focus.FocusImpl.run(FocusImpl.scala:22)
	at monocle.internal.focus.FocusImpl$.apply(FocusImpl.scala:33)
	at monocle.internal.focus.AppliedFocusImpl$.apply(AppliedFocusImpl.scala:13)

This is actually related to Focus not handling existential types gracefully, see #1201

case class Foo[T](content: Map[String, Foo[?]])

given Index[Foo[?], String, Foo[?]] = ...

Focus[Foo[?]](_.index("abc")) // Can't resolve the given Index instance

I tried to but could not reproduce the issue from the opening post. Here is also a somewhat minimized version:

import java.time.Instant
import monocle.Focus
import monocle.Focus.focus
import monocle.function.Index

enum LDP:
  case Container(content: Map[String, LDP], created: Instant = Instant.now)
  case TextResource(content: String, created: Instant = Instant.now)
end LDP

import LDP._

given Index[LDP, String, LDP] =
  Index(key => Focus[LDP](_.as[Container].content.index(key)))

given [S, I](using Index[S, I, S]): Index[S, List[I], S] =
  Index {
    case Nil => Focus[S]()
    case key :: keys => Focus[S](_.index(key).index(keys))
  }

val container = Container(Map("foo" -> Container(Map("bar" -> TextResource("banana")))))

container.focus(_.index(List("foo", "bar")).as[TextResource]).getOption