kind-projector returns 奇怪的结果
kind-projector returns strange results
我有这些类型:
SomeTypeClass
具有一个类型参数类型 * => * => *
的更高类型
trait SomeTypeClass[P[_, _]] {
def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: P[A, B])
(implicit ev: Strong[P],
ev2: Choice[P],
ev3: Applicative[F]): P[S, T]
}
Target
接受三个类型参数:
类型构造函数 F[_]
和两个多态类型 A, B
case class Target[F[_], A, B](f: A => F[B])
我想实现 Target 的 SomeTypeClass 实例。
我正在使用 kind-projector 插件来创建部分应用的类型。
我想要的方法签名应该是:
implicit def instance: SomeTypeClass[Target[F, *, *]] = new SomeTypeClass[Target[F, *, *]] {
override def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: Target[F, A, B])
(implicit ev: Strong[Target[F, *, *]],
ev2: Choice[Target[F, *, *]],
ev3: Applicative[F]): Target[F, S, T] = ???
}
我试过用两个星形参数来使用这个语法:
implicit def instance[F[_]]: SomeTypeClass[Target[F, *, *]] = new SomeTypeClass[Target[F, *, *]] {
override def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: Target[F, A, B])
(implicit ev: Strong[Target[F, *, *]],
ev2: Choice[Target[F, *, *]],
ev3: Applicative[F]): Target[F, S, T] = ???
}
但是在实例级别声明的 F[_]
隐藏了在测试方法中声明的 F[_]
(我希望它们是相同的 F),所以我已经转向 λ 语法并且得到两个不同的不需要的结果。
第一个使用 λ[(F, A, B) => Target[F, A, B]]
为 pab
参数生成的,
pab: Target[A, B, B]
而不是 pab: Target[F, A, B]
并且对于 return 类型 Target[S, T, B]
而不是 Target[F, S, T]
第二个在三重类型 lambda 参数的末尾使用 F(为什么???)
λ[(A, B, F) => Target[F, A, B]]
为 pab
参数和return 类型,但是
对于每个隐式参数,类型 Strong[λ[(A, B, F) => Target[F, A, B]]]
而不是
Strong[Target[F, *, *]]]
完整代码:
import cats.Applicative
import cats.arrow.{Choice, Strong}
final case class Target[F[_], A, B](f: A => F[B])
trait SomeTypeClass[P[_, _]] {
def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: P[A, B])
(implicit ev: Strong[P],
ev2: Choice[P],
ev3: Applicative[F]): P[S, T]
}
object SomeTypeClass {
implicit def instance1: SomeTypeClass[λ[(F, A, B) => Target[F, A, B]]] = new SomeTypeClass[λ[(F, A, B) => Target[F, A, B]]] {
override def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: Target[A, B, B])
(implicit ev: Strong[Target],
ev2: Choice[Target],
ev3: Applicative[F]): Target[S, T, B] = ???
}
implicit def instance2: SomeTypeClass[λ[(A, B, F) => Target[F, A, B]]] = new SomeTypeClass[λ[(A, B, F) => Target[F, A, B]]] {
override def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: Target[F, A, B])
(implicit ev: Strong[λ[(A, B, F) => Target[F, A, B]]],
ev2: Choice[λ[(A, B, F) => Target[F, A, B]]],
ev3: Applicative[F]): Target[F, S, T] = ???
}
}
我可以使用这个插件实现我想要的语法吗?
为什么这个插件会生成不同的类型
对于不同顺序的 lambda 类型 'parameters'?
如果我明白了
But the F[_]
declared at the instance level shadows the F[_]
declared at the test method (I want them to be the same F
)
正确地,您希望 SomeTypeClass[Target[...]]
的实例修复 test
的 F[_]
参数。但这对于 test
类型签名来说根本不可能。一旦你有(例如)
val inst = implicitly[SomeTypeClass[Target[...]]
可以打电话
val res1 = inst.test[List, ...]
val res2 = inst.test[Option, ...]
类型 lambda 不提供解决此问题的方法。您需要将 F[_]
参数移动到 SomeTypeClass
或实施
implicit def instance[F[_]]: SomeTypeClass[Target[F, *, *]] = new SomeTypeClass[Target[F, *, *]] {
override def test[G[_], S, T, A, B](f: (A => G[B]) => S => G[T])
(pab: Target[F, A, B])
(implicit ev: Strong[Target[F, *, *]],
ev2: Choice[Target[F, *, *]],
ev3: Applicative[G]): Target[G, S, T] = ???
}
我认为这是不可能的,因为你不能将 pab.f
传递给 f
。
编辑:wander
的类型
class (Choice p, Strong p) => Traversing p where
traverse' :: Traversable f => p a b -> p (f a) (f b)
traverse' = wander traverse
wander :: (forall f. Applicative f => (a -> f b) -> s -> f t) -> p a b -> p s t
wander f pab = dimap (\s -> Baz $ \afb -> f afb s) sold (traverse' pab)
是一个rank-2 type which aren't supported in Scala directly; instead you need to introduce a helper (which can't just be a type alias as it is in Control.Lens.Type
)
trait Traversal[S, T, A, B] {
def apply[F[_]: Applicative](f: A => F[B]): S => F[T]
}
然后
trait Traversing[P[_, _]] extends Strong[P] with Choice[P] {
def wander[S, T, A, B](t: Traversal[S, T, A, B], pab: P[A, B]): P[S, T]
}
implicit def instance[F[_]: Applicative]: Traversing[Target[F, *, *]] = new Traversing[Target[F, *, *]] {
def wander[S, T, A, B](t: Traversal[S, T, A, B], pab: Target[F, A, B]): Target[F, S, T] = Target(t(pab.f))
// define Strong and Choice methods too
}
应该可以。 (虽然我不确定这是猫处理 Strong
和 Choice
要求的方式。)
我有这些类型:
SomeTypeClass
具有一个类型参数类型 * => * => *
trait SomeTypeClass[P[_, _]] {
def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: P[A, B])
(implicit ev: Strong[P],
ev2: Choice[P],
ev3: Applicative[F]): P[S, T]
}
Target
接受三个类型参数:
类型构造函数 F[_]
和两个多态类型 A, B
case class Target[F[_], A, B](f: A => F[B])
我想实现 Target 的 SomeTypeClass 实例。
我正在使用 kind-projector 插件来创建部分应用的类型。
我想要的方法签名应该是:
implicit def instance: SomeTypeClass[Target[F, *, *]] = new SomeTypeClass[Target[F, *, *]] {
override def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: Target[F, A, B])
(implicit ev: Strong[Target[F, *, *]],
ev2: Choice[Target[F, *, *]],
ev3: Applicative[F]): Target[F, S, T] = ???
}
我试过用两个星形参数来使用这个语法:
implicit def instance[F[_]]: SomeTypeClass[Target[F, *, *]] = new SomeTypeClass[Target[F, *, *]] {
override def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: Target[F, A, B])
(implicit ev: Strong[Target[F, *, *]],
ev2: Choice[Target[F, *, *]],
ev3: Applicative[F]): Target[F, S, T] = ???
}
但是在实例级别声明的 F[_]
隐藏了在测试方法中声明的 F[_]
(我希望它们是相同的 F),所以我已经转向 λ 语法并且得到两个不同的不需要的结果。
第一个使用 λ[(F, A, B) => Target[F, A, B]]
为 pab
参数生成的,
pab: Target[A, B, B]
而不是 pab: Target[F, A, B]
并且对于 return 类型 Target[S, T, B]
而不是 Target[F, S, T]
第二个在三重类型 lambda 参数的末尾使用 F(为什么???)
λ[(A, B, F) => Target[F, A, B]]
为 pab
参数和return 类型,但是
对于每个隐式参数,类型 Strong[λ[(A, B, F) => Target[F, A, B]]]
而不是
Strong[Target[F, *, *]]]
完整代码:
import cats.Applicative
import cats.arrow.{Choice, Strong}
final case class Target[F[_], A, B](f: A => F[B])
trait SomeTypeClass[P[_, _]] {
def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: P[A, B])
(implicit ev: Strong[P],
ev2: Choice[P],
ev3: Applicative[F]): P[S, T]
}
object SomeTypeClass {
implicit def instance1: SomeTypeClass[λ[(F, A, B) => Target[F, A, B]]] = new SomeTypeClass[λ[(F, A, B) => Target[F, A, B]]] {
override def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: Target[A, B, B])
(implicit ev: Strong[Target],
ev2: Choice[Target],
ev3: Applicative[F]): Target[S, T, B] = ???
}
implicit def instance2: SomeTypeClass[λ[(A, B, F) => Target[F, A, B]]] = new SomeTypeClass[λ[(A, B, F) => Target[F, A, B]]] {
override def test[F[_], S, T, A, B](f: (A => F[B]) => S => F[T])
(pab: Target[F, A, B])
(implicit ev: Strong[λ[(A, B, F) => Target[F, A, B]]],
ev2: Choice[λ[(A, B, F) => Target[F, A, B]]],
ev3: Applicative[F]): Target[F, S, T] = ???
}
}
我可以使用这个插件实现我想要的语法吗?
为什么这个插件会生成不同的类型
对于不同顺序的 lambda 类型 'parameters'?
如果我明白了
But the
F[_]
declared at the instance level shadows theF[_]
declared at the test method (I want them to be the sameF
)
正确地,您希望 SomeTypeClass[Target[...]]
的实例修复 test
的 F[_]
参数。但这对于 test
类型签名来说根本不可能。一旦你有(例如)
val inst = implicitly[SomeTypeClass[Target[...]]
可以打电话
val res1 = inst.test[List, ...]
val res2 = inst.test[Option, ...]
类型 lambda 不提供解决此问题的方法。您需要将 F[_]
参数移动到 SomeTypeClass
或实施
implicit def instance[F[_]]: SomeTypeClass[Target[F, *, *]] = new SomeTypeClass[Target[F, *, *]] {
override def test[G[_], S, T, A, B](f: (A => G[B]) => S => G[T])
(pab: Target[F, A, B])
(implicit ev: Strong[Target[F, *, *]],
ev2: Choice[Target[F, *, *]],
ev3: Applicative[G]): Target[G, S, T] = ???
}
我认为这是不可能的,因为你不能将 pab.f
传递给 f
。
编辑:wander
class (Choice p, Strong p) => Traversing p where
traverse' :: Traversable f => p a b -> p (f a) (f b)
traverse' = wander traverse
wander :: (forall f. Applicative f => (a -> f b) -> s -> f t) -> p a b -> p s t
wander f pab = dimap (\s -> Baz $ \afb -> f afb s) sold (traverse' pab)
是一个rank-2 type which aren't supported in Scala directly; instead you need to introduce a helper (which can't just be a type alias as it is in Control.Lens.Type
)
trait Traversal[S, T, A, B] {
def apply[F[_]: Applicative](f: A => F[B]): S => F[T]
}
然后
trait Traversing[P[_, _]] extends Strong[P] with Choice[P] {
def wander[S, T, A, B](t: Traversal[S, T, A, B], pab: P[A, B]): P[S, T]
}
implicit def instance[F[_]: Applicative]: Traversing[Target[F, *, *]] = new Traversing[Target[F, *, *]] {
def wander[S, T, A, B](t: Traversal[S, T, A, B], pab: Target[F, A, B]): Target[F, S, T] = Target(t(pab.f))
// define Strong and Choice methods too
}
应该可以。 (虽然我不确定这是猫处理 Strong
和 Choice
要求的方式。)