代码之家  ›  专栏  ›  技术社区  ›  Miles Sabin

我们能在scala中定义一个更高类型级别的标识函数吗?

  •  16
  • Miles Sabin  · 技术社区  · 14 年前

    在scala中,我们可以为较低类型(如so)定义类型级别标识函数,

    type Id[A] = A
    

    我们还可以为更高级的同类定义类似的东西吗?也就是说,我们能把空白填上吗?

    type HKId[A[...]] = ...
    

    所以类似于hkid[list]的东西会让我们回到list类型的构造函数?

    自由名称的绑定

    type Foo[X] = List[X]
    val l : Foo[Int] = List(1, 2, 3)
    

    可能会导致我们期望更高类型级别的身份看起来像,

    type HKId[A[X]] = A[X]
    

    但是scalac抱怨在RHS上找不到类型X。

    有什么聪明的编码方法可以做到这一点吗?还是现在不可能?

    3 回复  |  直到 13 年前
        1
  •  13
  •   retronym    13 年前

    X 在里面 type HKId[A[X]] = ... 是高阶类型参数。它的作用域是类型参数子句,通常在类型约束中引用。见规范第4.4节:

    上述范围限制为 推广到嵌套类型的情况 参数子句,其中声明 高阶类型参数。 高阶类型参数(类型 类型参数t)的参数为 只在他们的 环境参数子句(可能 包括更深嵌套处的子句 水平)并在t的范围内。 因此,他们的名字只能是 两人的名字不同 其他可见参数。自从 高阶类型参数的名称 因此,它们往往是无关紧要的 用__________ 可见的。

    不久前,我们讨论了为类型函数添加文本语法的可能性,例如 [A] Either[Int, A] . 这对scalaz非常有用。同时,我们使用亚历克赛的答案中的技巧,用 PartialApplyXofY traits . 推断可能会更好,但这要复杂得多,尽管 innocuous entry in Trac !)

    不管怎样,在那段时间里, Adriaan mentioned :

    很明显 实现一切合乎逻辑的 源自匿名类型 功能,因为我们目前没有 必要的基础设施 写高级亲属类型的人 别名,例如:

    键入mytypefun=[x,y]对[y,x]// 可取,但难以支撑 当前的实施(我们看 要推断的符号的类型参数 它的种类)

    更新

    结果发现你已经很接近了:

    def hk[_[_]] = (); 
    hk[({type A[X] = X})#A]
    

    或者有点创意:

    def hk[_[_]] = (); hk[({type \[X] = X}) # \ ]
    def hk[_[_]] = (); hk[({type λ[α]=α})#λ ]
    
        2
  •  5
  •   Alexey Romanov    14 年前

    找不到一种方法 type 但这是可行的:

    class HKId[A[_]] { 
      type Value[X] = A[X] 
    }
    

    编译:

    scala> List(1): HKId[List]#Value[Int]
    res2: List[Int] = List(1)
    

    但这并不是:

    scala> List(1): HKId[List]#Value[Boolean]
    <console>:7: error: type mismatch;
     found   : Int(1)
     required: Boolean
           List(1): HKId[List]#Value[Boolean]
    
        3
  •  3
  •   Miles Sabin    13 年前

    从@反义词中抢走正确答案似乎有点不公平,但看起来我们可以更接近我所追求的解决方案,

    scala> type HKId[A[_]] = { type λ[X] = A[X] }
    defined type alias HKId
    
    scala> def foo[C[_]] : C[Int] = null.asInstanceOf
    foo: [C[_]]=> C[Int]
    
    scala> foo[List]
    res0: List[Int] = null
    
    scala> foo[HKId[List]#λ]
    res1: List[Int] = null
    

    我不知道为什么现在看起来很明显,但一年前不明显…也许是因为从那时起,我们都更习惯于看“羊羔”。