2

case class User2 つのケース クラスがあります。それらを&と呼びましょうcase class Ticket。これらのケース クラスは両方とも、同じTypeClass、この場合は Argonaut の のメンバーであるために必要な操作を実装しEncodeJsonます。

両方が拡張する空のマーカー タイプを作成せずに、これら 2 つの別々のタイプを同じものとして表示することは可能ですか?

trait Marker
case class User extends Marker
case class Ticket extends Marker

これを具体的にするために、これらのケース クラスを返す 2 つの別個の関数があります。

case class GetUser(userId: Long) extends Service[Doesn't Matter, User] {
  def apply(req: Doesn't Matter): Future[User] = {
    magical and awesome business logic 
    return Future[User]
   }
}

case class GetTicket(ticketId: Long) extends Service[Doesn't Matter, Ticket] {
  def apply(req: Doesn't Matter): Future[Ticket] = {
    magical and awesome business logic 
    return Future[Ticket]
   }
}

これら 2 つのサービスが同じ型 (この場合は ) を返すように構成したいと思いますargonaut.Jsonが、暗黙的な変換に対するコンパイラの応答は "LOLNO" です。

implicit def anyToJson[A](a: A)(implicit e: EncodeJson[A]): Json = e(a)

何か案は?ありがとう!

4

1 に答える 1

1

これらのケース クラスがある場合:

case class User(id: Long, name: String)
case class Ticket(id: Long)

そして、これらのインスタンス:

import argonaut._, Argonaut._

implicit val encodeUser: EncodeJson[User] =
  jencode2L((u: User) => (u.id, u.name))("id", "name")

implicit val encodeTicket: EncodeJson[Ticket] = jencode1L((_: Ticket).id)("id")

そして、次のサービス (私は Finagle の表現を使用しています):

import com.twitter.finagle.Service
import com.twitter.util.Future

case class GetUser(id: Long) extends Service[String, User] {
  def apply(req: String): Future[User] = Future(User(id, req))
}

case class GetTicket(id: Long) extends Service[String, Ticket] {
  def apply(req: String): Future[Ticket] = Future(Ticket(id))
}

(これらはナンセンスですが、実際には問題ではありません。)

次に、暗黙的な変換を使用して戻り値の型を変更する代わりに、次のようにサービスを変換するメソッドを記述できます。

def toJsonService[I, O: EncodeJson](s: Service[I, O]): Service[I, Json] =
  new Service[I, Json] {
    def apply(req: I) = s(req).map(_.asJson)
  }

そして、これを他のサービスに適用します。

scala> toJsonService(GetTicket(100))
res7: com.twitter.finagle.Service[String,argonaut.Json] = <function1>

この機能をサービスまたはフィルターとして提供することもできます。または、関数を元に戻すことを気にしない場合は、GetTicket(100).andThen(_.map(_.asJson))直接使用することもできます。

重要な考え方は、暗黙的な変換を導入することは絶対的な最後の手段であり、代わりに型クラスのインスタンスを直接使用する必要があるということです。

于 2015-05-01T17:32:17.480 に答える