Finkle MacGraw
Finkle MacGraw

Reputation: 110

for-comprehension: type mismatch - required Option[?]

I am relatively new to using Scala in a project and stumbled over a problem I just don't understand.

This is my code. I annotated types for clarity:

val fcs = for {
      fc: Call <- funCalls
      ann: List[CapabilityArg] <- context.annotationOption(Annotations.CapabilityArguments, fc)
      arg: CapabilityArg <- ann
} yield CapabilityInfo(
      "CapabilityArgument", arg.id.name, new LSPRange, new LSPRange
)

which errors with:

type mismatch;
 found   : List[LSPServer.this.CapabilityInfo]
 required: Option[?]

If if remove the last line in the for-comprehension, the error disappears. Shouldn't that line be okay, since I only map over a List[CapabilityArg]?

Thank you in advance!

Upvotes: 0

Views: 925

Answers (2)

Finkle MacGraw
Finkle MacGraw

Reputation: 110

Thanks to @Tim I came up with this solution:

val fcs = for {
      fc: Call <- funCalls : Array[Call]
      ann: List[CapabilityArg] <- context.annotationOption(Annotations.CapabilityArguments, fc) : Option[List[CapabilityArg]]
} yield {
      ann.toArray.map(arg =>
        CapabilityInfo("CapabilityArgument", arg.id.name, new LSPRange, new LSPRange)
      )
}

return fcs.flatten

I switched funCalls to type Array[Call] so I yield an Array[CapabilityInfo] that is then packed into another array. The result is then flattened to give me the desired one-dimensional array of all CapabilityInfos.

In hindsight I probably should have gone for a regular nested for-each construct?!

Upvotes: 0

Tim
Tim

Reputation: 27421

The problem is that you are mixing List and Option in the for. The result collection type of a for is the collection type of the first line, which I assume is Option. The last line in the for will generate multiple values but Option can only hold one value.

This is probably what you want:

val fcs = for {
  fc: Call <- funCalls
  ann: List[CapabilityArg] <- context.annotationOption(Annotations.CapabilityArguments, fc)
} yield {
  ann.map(arg => CapabilityInfo(
    "CapabilityArgument", arg.id.name, new LSPRange, new LSPRange
  ))
}

This will return Option[List[CapabilityInfo]]

Upvotes: 4

Related Questions