如何正确定义lambda类型? [英] How to define type lambda properly?

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

问题描述

我使用=:=作为示例类型lambda来制作简单的最小示例.

I used =:= as example type lambda for purpose of making simple minimal example.

=:=类型有两个参数,我想在类型级别使用一个参数.

=:= type take two arguments, I'd like to curry one at type level.

我采用朴素的实现type Curry[G] = {type l[L] = L =:= G},但在实际使用中会导致错误:

I take naive implementation type Curry[G] = {type l[L] = L =:= G} but in practical uses it causes errors:

type X = Int
type Y = Int

type CurryInt[T] = T =:= Int
type Curry[G] = {type l[L] = L =:= G}
type CurrStatic = {type l[L] = L =:= Int}
object CurryObj {type l[L] = L =:= Int}

trait Apply[P[_], T]
implicit def liftApply[P[_], T](implicit ev : P[T]) = new Apply[P,T] {}

implicitly[Apply[CurryInt, Y]] // ok
implicitly[Apply[Curry[X]#l, Y]] // fails
implicitly[Apply[Curry[X]#l, Y]](liftApply) // fails
implicitly[Apply[Curry[X]#l, Y]](liftApply[Curry[X]#l, Y]) // ok
implicitly[Apply[CurrStatic#l, Y]] // fails
implicitly[Apply[CurryObj.l, Y]] // ok

类型推断在这里中断.我应该如何定义lambda类型以使其正常工作?

Type inference breaks here. How should I define type lambdas to make it work?

推荐答案

考虑此示例的简化版本:

Consider this simplified version of your example:

trait Secret
type Curry = { type l[L] = Secret }

def foo[P[_], T](ev : P[T]) = ???
val bar: Curry#l[Int] = ???

foo(bar)

当调用foo时,值bar只是类型Secret,编译器不知道您的特定Secret来自何处.

When calling foo the value bar is simply of type Secret, the compiler doesn't know from where your particular Secret comes from.

您的bar值只是一个Secret,并且不保留指向Curry#l[Int]的信息.

Your bar value is just a Secret, and it doesn't maintain information pointing back to Curry#l[Int].

编译器无法推断P => Curry#lT => Int.

尽管使用Curry#l[Int]而不是Secret注释了类型,但编译器仅看到Secret并丢失了Curry#l上下文.

The compiler only sees the Secret and loses the Curry#l context despite annotating the type with Curry#l[Int] instead of Secret.

另一个示例(来自 this 问题),暴露出类似的行为:

Another example (coming from this question), exposing a similar behaviour:

trait Curry { type l }
trait CurryB extends Curry { type l = String }

def foo[P <: Curry](x: P#l) = ???
val bar: CurryB#l = ???

foo(bar)


CurryObj的情况有所不同,请考虑CurryInt#lCurry#lCurrStatic#l只是类型别名.相反,CurryObj.l是实际类型,是具体对象CurryObj的一部分.


CurryObj situation is different, consider that CurryInt#l, Curry#l, and CurrStatic#l are just type aliases. CurryObj.l, instead, is an actual type, part of the concrete object CurryObj.

让我们看看这个(REPL):

Let's have a look to this (REPL):

scala> trait Secret
defined trait Secret

scala> type Curry = { type l[L] = Secret }
defined type alias Curry

scala> object CurryObj { type l[L] = Secret }
defined object CurryObj

scala> object S extends Secret
defined object S

scala> val foo0: Curry#l[Int] = S
foo0: Secret = S$@2c010477

scala> val foo1: CurryObj.l[Int] = S
foo1: CurryObj.l[Int] = S$@2c010477

请注意,将立即解析类型别名Curry#l[Int]-> Secret,而不是保留实际的类型CurryObj.l[Int].

Note that the type alias Curry#l[Int] -> Secret is resolved immediately, instead the actual type CurryObj.l[Int] is kept.

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

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