gpt4 book ai didi

scala - 使用 Unapply 提取相同的类型类

转载 作者:行者123 更新时间:2023-12-03 04:55:29 26 4
gpt4 key购买 nike

我有以下情况,给定两种类型 MAMB,我希望能够证明它们不仅具有 Applicative 而且它们都具有相同的基础形状。我尝试执行以下操作:

type UnapplyM[TC[_[_]], MA, M0[_]] = Unapply[TC, MA]{ type M[X] = M0[X] }

implicit def thing[MA, MB, M[_]](implicit un: UnapplyM[Applicative,MA,M], un2: UnapplyM[Applicative,MB,M]) = ...

但继续遇到不同的隐式(即这不起作用。)类似的事情可以通过对 UnapplyA 类型参数进行类型投影来完成,并且可以工作.

有没有办法采用这两种类型并能够证明它们实际上受到相同类型类实例的支持?

最佳答案

首先我要说的是,完整的答案将是一个很长的故事,我已经讲了其中的很大一部分 in a blog post从去年夏天开始,所以我将在这里浏览一些细节,并仅提供 Catsthing 的工作实现。 .

另一个介绍性说明:该机制现在存在于 Scalaz 中,并且 some of the "review"my pull request添加它是我很高兴猫存在的众多原因之一。 :)

首先是一个完全不透明的类型类,我什至不会尝试在这里激发它:

case class SingletonOf[T, U <: { type A; type M[_] }](
widen: T { type A = U#A; type M[x] = U#M[x] }
)

object SingletonOf {
implicit def mkSingletonOf[T <: { type A; type M[_] }](implicit
t: T
): SingletonOf[T, t.type] = SingletonOf(t)
}

接下来我们可以定义一个 IsoFunctor,因为 Cats 目前似乎还没有:

import cats.arrow.NaturalTransformation

trait IsoFunctor[F[_], G[_]] {
def to: NaturalTransformation[F, G]
def from: NaturalTransformation[G, F]
}

object IsoFunctor {
implicit def isoNaturalRefl[F[_]]: IsoFunctor[F, F] = new IsoFunctor[F, F] {
def to: NaturalTransformation[F, F] = NaturalTransformation.id[F]
def from: NaturalTransformation[F, F] = to
}
}

我们可以使用比 IsoFunctor 更简单的东西来完成我们即将要做的事情,但它是一个很好的原则性类型类,而且也是我在 Scalaz 中使用的,所以我会坚持使用就在这里。

接下来是一个将两个 Unapply 实例捆绑在一起的新 Unapply:

import cats.Unapply

trait UnapplyProduct[TC[_[_]], MA, MB] {
type M[X]; type A; type B
def TC: TC[M]
type MA_ = MA
def _1(ma: MA): M[A]
def _2(mb: MB): M[B]
}

object UnapplyProduct {
implicit def unapplyProduct[
TC[_[_]], MA0, MB0,
U1 <: { type A; type M[_] },
U2 <: { type A; type M[_] }
](implicit
sU1: SingletonOf[Unapply[TC, MA0], U1],
sU2: SingletonOf[Unapply[TC, MB0], U2],
iso: IsoFunctor[U1#M, U2#M]
): UnapplyProduct[TC, MA0, MB0] {
type M[x] = U1#M[x]; type A = U1#A; type B = U2#A
} = new UnapplyProduct[TC, MA0, MB0] {
type M[x] = U1#M[x]; type A = U1#A; type B = U2#A
def TC = sU1.widen.TC
def _1(ma: MA0): M[A] = sU1.widen.subst(ma)
def _2(mb: MB0): M[B] = iso.from(sU2.widen.subst(mb))
}
}

作为历史旁注,UnapplyProduct 在 Scalaz 中存在了四年才出现任何有用的实例。

现在我们可以写这样的东西:

import cats.Applicative

def thing[MA, MB](ma: MA, mb: MB)(implicit
un: UnapplyProduct[Applicative, MA, MB]
): Applicative[un.M] = un.TC

然后:

scala> import cats.data.Xor
import cats.data.Xor

scala> thing(Xor.left[String, Int]("foo"), Xor.right[String, Char]('a'))
res0: cats.Applicative[[x]cats.data.Xor[String,x]] = cats.data.XorInstances$$anon$1@70ed21e4

我们已经成功地让编译器识别如何分解这些 Xor 类型,以便它可以看到相关的 Applicative 实例(我们返回该实例) )。

关于scala - 使用 Unapply 提取相同的类型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35845572/

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