Stack Overflow Asked by six_minute_abs on December 18, 2021
A and I are doing some work with circe to encode/decode some ADTs and we ran into some functionality we fundamentally don’t understand. The examples given in the circe documentation work as expected, but upon drilling down – it’s not clear why the decoding example works and therefore we are having a hard time reasoning about how to modify if needed.
The functionality (from Circe Examples about ADTs):
import cats.syntax.functor._
import io.circe.{ Decoder, Encoder }, io.circe.generic.auto._
import io.circe.syntax._
object GenericDerivation {
// Encoder Redacted
implicit val decodeEvent: Decoder[Event] =
List[Decoder[Event]](
Decoder[Foo].widen,
Decoder[Bar].widen,
Decoder[Baz].widen,
Decoder[Qux].widen
).reduceLeft(_ or _)
}
I get it – basically pick the first decoder that works from this list- makes sense BUT(!)
or
appears to be a unary function taking a by name argument. Type signature is:
final def or[AA >: A](d: => Decoder[AA]): Decoder[AA]
And reduceLeft
(from IterableOnce) requires a binary function. Type Signature is:
def reduceLeft[B >: A](op: (B, A) => B): B
And then my brain exploded. I am clearly missing something and can’t figure it out.
The example most decidedly works to convert ADTs. Why/how does this work given that the or
function doesn’t seem to be meeting the required type by reduceLeft
?
Consider the following simplified analogy
case class Score(v: Double) {
def add(that: Score): Score = Score(this.v + that.v)
}
val l = List[Score](Score(1.1), Score(2.2), Score(0.1))
l.reduceLeft((a: Score, b: Score) => a.add(b)) // unsugared
l.reduceLeft((a: Score, b: Score) => a add b) // infix notation
l.reduceLeft(_ add _) // anonymous function placeholder parameter
Note the usage of infix notation and anonymous function placeholder parameter
Answered by Mario Galic on December 18, 2021
or
is a method of one parameter but don't forget about this
.
decoder1.or(decoder2)
(aka decoder1 or decoder2
) is a binary function with respect to decoder1
, decoder2
.
+
is also a method of one parameter
final abstract class Int private extends AnyVal {
...
/** Returns the sum of this value and `x`. */
def +(x: Int): Int
...
}
but you can still add two Int
s: 1 + 1
aka 1.+(1)
.
All methods have one "parameter" more than listed in their signatures, namely this
.
(All ordinary parameters are resolved statically and this
is resolved dynamically.)
Answered by Dmytro Mitin on December 18, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP