简体   繁体   中英

Scala implicit error with implicit parameter

I have the following in my file

import cats._
import cats.syntax.all._

implicit val showPrimaryFieldSchema: Show[PrimaryFieldSchema] = pf => {
        s"PRIMARY_ID ${pf.fName} ${pf.fType.show}"
    }

when i write the following:

implicit def showVertexSchema(implicit pShow: Show[PrimaryFieldSchema], npShow: Show[NonPrimaryFieldSchema] ): Show[VertexSchema] = vSchema => {
        s"""VERTEX ${vSchema.vName} (${vSchema.pField.show}, ${vSchema.nPFields.map(np => npShow.show(np)).mkString(", ")}) WITH primary_id_as_attribute="FALSE""""
    }

I get the following error:

value show is not a member of com.elsevier.entellect.tigergraph.schemabuilder.DataTypes.PrimaryFieldSchema [error] s"""VERTEX ${vSchema.vName} (${vSchema.pField.show}, ${vSchema.nPFields.map(np => npShow.show(np)).mkString(", ")}) WITH primary_id_as_attribute="FALSE""""

However the following code works:

implicit def showVertexSchema(implicit pShow: Show[PrimaryFieldSchema], npShow: Show[NonPrimaryFieldSchema] ): Show[VertexSchema] = vSchema => {
        s"""VERTEX ${vSchema.vName} (${pShow.show(vSchema.pField)}, ${vSchema.nPFields.map(np => npShow.show(np)).mkString(", ")}) WITH primary_id_as_attribute="FALSE""""
    }

So I wonder really why

vSchema.pField.show

not ok at all here. implicit pShow: Show[PrimaryFieldSchema] is a category1 implicit, and a parameter. so not sure

Can someone explain?

EDIT1

sealed trait Schema
final case class VertexSchema(vName: String, pField: PrimaryFieldSchema, nPFields: List[NonPrimaryFieldSchema]) extends Schema
final case class EdgePairSchema(FROM: VertexSchema, TO: VertexSchema)
final case class EdgeSchema(eName: String, pairs: List[EdgePairSchema], fields: List[NonPrimaryFieldSchema], Directed: Boolean, erName: Option[String]) extends Schema
final case class GraphSchema(gName: String, vertexSchemas: List[VertexSchema] = List(), edgeSchemas: List[EdgeSchema] = List()) extends Schema

sealed trait FieldSchema
final case class PrimaryFieldSchema(fName: String, fType: FieldType, index: Boolean = false) extends FieldSchema
final case class NonPrimaryFieldSchema(fName: String, fType: FieldType, index: Boolean = false) extends FieldSchema

sealed trait FieldType
sealed trait SimpleFieldType extends FieldType
final case object INT extends SimpleFieldType
final case object UINT extends SimpleFieldType
final case object FLOAT extends SimpleFieldType
final case object DOUBLE extends SimpleFieldType
final case object BOOL extends SimpleFieldType
final case object STRING extends SimpleFieldType
final case object DATETIME extends SimpleFieldType
sealed trait ComplexFieldType extends FieldType
final case class LIST(fieldType: SimpleFieldType) extends ComplexFieldType
final case class SET(fieldType: SimpleFieldType)  extends ComplexFieldType



implicit val showINTType: Show[INT.type] = _.toString
implicit val showUINTType: Show[UINT.type] = _.toString
implicit val showFLOATType: Show[FLOAT.type] = _.toString
implicit val showDOUBLEType: Show[DOUBLE.type] = _.toString
implicit val showBOOLType: Show[BOOL.type] = _.toString
implicit val showSTRINGType: Show[STRING.type] = _.toString
implicit val showDATETIMEType: Show[DATETIME.type] = _.toString
implicit val showLISTType : Show[LIST] = list => s"LIST<${list.fieldType.toString}>"
implicit val showSETType : Show[SET] = set => s"SET<${set.fieldType.toString}>"

implicit val showFieldType: Show[FieldType] = {
    case INT => INT.show
    case UINT => UINT.show
    case FLOAT => FLOAT.show
    case BOOL => BOOL.show
    case DOUBLE => DOUBLE.show
    case STRING => STRING.show
    case DATETIME => DATETIME.show
    case list@LIST(_) => list.show
    case set@SET(_) => set.show
}


implicit val showPrimaryFieldSchema: Show[PrimaryFieldSchema] = pf => {
    s"PRIMARY_ID ${pf.fName} ${pf.fType.show}"
}

implicit val showNonPrimaryFieldSchemaa: Show[NonPrimaryFieldSchema] = pf => {
    s"${pf.fName} ${pf.fType.show}"
}

implicit def showVertexSchema(implicit pShow: Show[PrimaryFieldSchema], npShow: Show[NonPrimaryFieldSchema] ): Show[VertexSchema] = vSchema => {
    s"""VERTEX ${vSchema.vName} (${pShow.show(vSchema.pField)}, ${vSchema.nPFields.map(np => npShow.show(np)).mkString(", ")}) WITH primary_id_as_attribute="FALSE""""
}

EDIT2

Same problem happen is i first comment out

/*implicit val showPrimaryFieldSchema: Show[PrimaryFieldSchema] = pf => {
    s"PRIMARY_ID ${pf.fName} ${pf.fType.show}"
}*/

and then i do

implicit def showVertexSchema(implicit pShow: Show[PrimaryFieldSchema], npShow: Show[NonPrimaryFieldSchema] ): Show[VertexSchema] = vSchema => {

    implicit val showPrimaryFieldSchema1: Show[PrimaryFieldSchema] = pf => {
        s"PRIMARY_ID ${pf.fName} ${pf.fType.show}"
    }

    s"""VERTEX ${vSchema.vName} (${vSchema.pField.show}, ${vSchema.nPFields.map(np => npShow.show(np)).mkString(", ")}) WITH primary_id_as_attribute="FALSE""""
}
//> value show is not a member of A$A7.this.PrimaryFieldSchema

then if i remove the implicit value but only keep the parameter, of course it works as a charm.

There seem to be an issue with the fact that 2 implicit of the same precedence are in scope maybe?

EDIT3

I added the following scalac option and i get

toShow is not a valid implicit value for vSchema.pField.type => ?{def show: ?} because:
ambiguous implicit values:
 both lazy value showPrimaryFieldSchema in class A$A31 of type cats.Show[A$A31.this.PrimaryFieldSchema]
 and value pShow of type cats.Show[A$A31.this.PrimaryFieldSchema]
 match expected type cats.Show[A$A31.this.PrimaryFieldSchema]
    s"""VERTEX ${vSchema.vName} (${vSchema.pField.show}, ${vSchema.nPFields.map(np => npShow.show(np)).mkString(", ")}) WITH primary_id_as_attribute="FALSE""""

This is the kind of feedback i would expect per default. 

However is that correct, i do not really get the implicit resolution rule here. Doesn't precedence play ?

Perpahs because you have conflicting Show[PrimaryFieldSchema] and Show[NonPrimaryFieldSchema] implicits:

// if you will remote implicit here 
val showPrimaryFieldSchema: Show[PrimaryFieldSchema] = pf => {
    s"PRIMARY_ID ${pf.fName} ${pf.fType.show}"
}

// and also here
val showNonPrimaryFieldSchemaa: Show[NonPrimaryFieldSchema] = pf => {
    s"${pf.fName} ${pf.fType.show}"
}

// Another working version
//implicit def showVertexSchema(implicit pShow: Show[PrimaryFieldSchema], npShow: Show[NonPrimaryFieldSchema] ): Show[VertexSchema] = vSchema => {
//    This works because you are using `pShow` explicetly, so no conflict.
//    s"""VERTEX ${vSchema.vName} (${pShow.show(vSchema.pField)}, ${vSchema.nPFields.map(np => npShow.show(np)).mkString(", ")}) WITH primary_id_as_attribute="FALSE""""
//}


implicit def showVertexSchema(implicit pShow: Show[PrimaryFieldSchema], npShow: Show[NonPrimaryFieldSchema] ): Show[VertexSchema] = vSchema => {
        // this will work, because otherwise `pShow` and `showPrimaryFieldSchema` will be same type implicits in one scope
        show"""VERTEX ${vSchema.vName} (${vSchema.pField}, ${vSchema.nPFields.map(np => show"np").mkString(", ")}) WITH primary_id_as_attribute="FALSE""""
    }

Full example available in Scatie: https://scastie.scala-lang.org/9X0Sy5t0Qfu3pM6fHIZ50g

Or alternatevly you can do:

implicit val showPrimaryFieldSchema: Show[PrimaryFieldSchema] = pf => {
    s"PRIMARY_ID ${pf.fName} ${pf.fType.show}"
}

implicit val showNonPrimaryFieldSchemaa: Show[NonPrimaryFieldSchema] = pf => {
    s"${pf.fName} ${pf.fType.show}"
}

implicit val showVertexSchema: Show[VertexSchema] = vSchema => {
  show"""VERTEX ${vSchema.vName} (${vSchema.pField}, ${vSchema.nPFields.map(np => show"np").mkString(", ")}) WITH primary_id_as_attribute="FALSE""""
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM