gpt4 book ai didi

scala - Play JSON InvariantFunctor

转载 作者:行者123 更新时间:2023-12-04 22:31:26 25 4
gpt4 key购买 nike

Play 的 JSON library 包括 FunctorInvariant Functor :

我以前见过 Functor:

trait Functor[M[_]] extends Variant[M] {

def fmap[A, B](m: M[A], f: A => B): M[B]

}

但是,从概念上讲,为什么有必要为 f1 提供 f2InvariantFunctor 函数?
trait InvariantFunctor[M[_]] extends Variant[M] {

def inmap[A, B](m: M[A], f1: A => B, f2: B => A): M[B]

}

最佳答案

this answer 中,我快速解释了为什么 Writes 不是仿函数——即,为什么如果我们有 Writes[A] 和函数 A => B 我们不能像使用 Writes[B] 一样创建 Reads

正如我在那个答案中所指出的, Writes 不是一个普通的(协变)仿函数,而是一个逆变仿函数,这意味着如果我们有一个 Writes[A] 和一个函数 B => A ,我们可以创建一个 Writes[B]
Format 包含了 ReadsWrites 的功能,这意味着它既不是仿函数也不是逆变仿函数——但它是一个不变仿函数(而且它确实是唯一一个你会在上下文中遇到的具有不变仿函数实例的类型玩)。

要了解为什么会这样,假设我们有以下两种类型:

case class Foo(i: Int, s: String)
case class Bar(s: String, i: Int)

假设我们有一个 FormatFoo 实例:
import play.api.libs.json._
import play.api.libs.functional.syntax._

implicit val fooFormat = Json.format[Foo]

但是无论出于何种原因,我们都无法以相同的方式为 Bar 创建一个——我们希望从 Foo 的那个派生它。仅仅知道如何从 Bar 创建 Foo 是不够的,反之亦然,但是如果我们可以双向使用,我们可以对 Format 使用不变仿函数:
implicit val barFormat = fooFormat.inmap[Bar](
foo => Bar(foo.s, foo.i),
bar => Foo(bar.i, bar.s)
)

这是因为我们可以将 Format 视为一个双向管道,它允许我们放入 JsValue 并取出一些 A ,或者放入 A 并取出 JsValue 。如果我们想将双向管道 Format[A] 转换为双向管道 Format[B] ,我们需要两端的适配器(即 A => BB => A )。

关于scala - Play JSON InvariantFunctor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21990112/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com