类型更高的 lambda [英] Type lambda with higher kind

查看:29
本文介绍了类型更高的 lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Dotty 中给出以下内容:

In Dotty given the following:

object Domain {
  final case class Create(name: String) extends BaseCreate[Create] {
    override type Model = Domain
    override def service[F[_]](client: KeystoneClient[F]): CrudService[F, Domain, Create] = client.domains
  }
}
case class Domain(id: String)

class CrudService[F[_], Model, Create]
final class Domains[F[_]] extends CrudService[F, Domain, Domain.Create]

class KeystoneClient[F[_]] {
  val domains = new Domains[F]
}

trait BaseCreate[Create <: BaseCreate[Create]] {                                                                                                        
  type Model
  def service[F[_]](client: KeystoneClient[F]): CrudService[F, Model, Create]
}

我想简化"BaseCreate 这样我就可以像这样实现 Create:

I want to "simplify" BaseCreate such that I can implement Create like this:

final case class Create(name: String) extends BaseCreate.Aux[Domain, Create](_.domains)

我试过了:

object BaseCreate {
  abstract class Aux[M, Create](f: [F[_]] =>> KeystoneClient[F] => CrudService[F, M, Create]) extends BaseCreate[Create] {                                        
    type Model = M
    def service[F[_]](client: KeystoneClient[F]): CrudService[F, Model, Create] = f(client)
  }
}

但编译器抱怨:

Missing type parameter for [F[_$5]] =>> KeystoneClient[F] => CrudService[F, M, Create]

这对我来说没有意义.什么是正确的语法,如果有的话?

Which doesn't make sense to me. Whats the right syntax, if there is one?

使用此代码链接到 scastie

PS:我不想在 BaseCreate 中引入更多类型参数.尤其是 F 因为这意味着 Domain.Create 类需要是 final case class Create[F[_]] 而不是完全没有预期的解决方案.

PS: I don't want to introduce any more type parameters to BaseCreate. Especially the F since that would mean the class Domain.Create would need to be final case class Create[F[_]] which is not at all the intended solution.

推荐答案

我猜你很困惑 使用多态函数键入 lambdas.

I guess you confused type lambdas with polymorphic functions.

类型 lambda 将类型映射到类型,多态函数将值映射到值,只是其参数的类型可以变化.

A type lambda maps types to types, a polymorhic function maps values to values just type of its argument can vary.

对于类型 lambda,你应该使用 =>>,对于多态函数你应该使用普通的 =>(两次,即 [A] => (a: A) => f(a)).

For type lambdas you should use =>>, for polymorhic functions you should use ordinary => (twice i.e. [A] => (a: A) => f(a)).

应该是这样的

object BaseCreate {
  abstract class Aux[M, Create](f: [F[_]] => KeystoneClient[F] => CrudService[F, M, Create]) extends BaseCreate[Create] {
    type Model = M
    def service[F[_]](client: KeystoneClient[F]): CrudService[F, Model, Create] = f(client)
  }
}
   
final case class Create(name: String) extends BaseCreate.Aux[Domain, Create](
  [F[_]] => (client: KeystoneClient[F]) => client.domains
)

但它不能在 Dotty 0.28.0-bin-20200920-e99793e-NIGHTLY 中编译并出现错误

but it doesn't compile in Dotty 0.28.0-bin-20200920-e99793e-NIGHTLY with error

Found:    Object with PolyFunction {...}
Required: PolyFunction{
  apply: 
    [F[_$6]]
      (x$1: App.KeystoneClient[F]): 
        App.CrudService[F, App.Domain, App.Create]
}
    [F[_]] => (client: KeystoneClient[F]) => client.domains

似乎是一个错误.

这篇关于类型更高的 lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆