问题 在Scala中,是否有减少泛型类型的简化的简写?


我想打电话给Scalaz pure 将值放入State monad的方法。以下作品:

type IntState[A] = State[Int, A]
val a = "a".pure[IntState]
a(1)
    (Int, java.lang.String) = (1,a)

我也可以删除类型别名(感谢Scalaz的Pure.scala):

val a = "a".pure[({type T[A]=State[Int,A]})#T]
a(1)
    (Int, java.lang.String) = (1,a)

但这非常笨重。是否有更短的方法来合成这样的类型?就像函数文字的占位符语法一样,有类似的东西:

"a".pure[State[Int, *]]

5482
2017-10-04 05:00


起源

我不认为Scala有这样的语法糖,因为 michid引用了部分类型的应用 作为类型投影的效用的一个例子。 - Kipton Barros


答案:


对于Scala中的简明部分类型应用程序(arity-2),您可以将类型表示法中缀为以下内容。

type ![F[_, _], X] = TF { type ![Y] = F[X,  Y] }

"a".pure[(State!Int)# !]

请注意,我们可以为两个arity类型构造函数(或类型别名)添加表示法。


6
2017-10-04 14:29



我重命名第二个 ! 至 ?所以我可以写 (State!Int)#?。 - Daniel C. Sobral
对于类型成员,非操作员名称更可取,因此您可以在类型投影后跳过该空格,即: trait ![F[_, _], A] { type X[B] = F[A, B] }; foo[(State!Int)#X]。不要认为它比这更紧凑。 - Jesper Nordenberg


不确定这是否更好,但这是@kmizu前一天发推文的一种方法:

scala> trait TF {
     |   type Apply[A]
     | }
defined trait TF

scala> type Curried2[F[_, _]] = TF {
     |   type Apply[X] = TF {
     |     type Apply[Y] = F[X, Y]
     |   }
     | }
defined type alias Curried2

scala> "a".pure[Curried2[State]#Apply[Int]#Apply]
res7: scalaz.State[Int,java.lang.String] = scalaz.States$$anon$1@1dc1d18

您可以使用符号类型别名使其看起来更好一些。

scala> type ![F[_, _]] = TF {
     |   type ![X] = TF {
     |     type ![Y] = F[X, Y]
     |   }
     | }
defined type alias $bang

scala> "a".pure[![State]# ![Int]# !]
res9: scalaz.State[Int,java.lang.String] = scalaz.States$$anon$1@1740235

6
2017-10-04 05:52



当你想绑定第一个类型参数时会发生什么?我想你需要另一个版本的Curried2? - IttayD
@IttayD:这不会被称为currying,在这种情况下你最好使用lambda语法。 (Tony Morris在某些邮件列表中也注意到了lambda语法相对于Haskell的curried类型构造函数语法的这一小优势。)我在这个答案中建议的语法是模拟Haskell样式的部分类型应用程序。 ![State]# ! 相当于 State 在哈斯克尔, ![State]# ![Int]# ! 至 State Int 等等 - missingfaktor
@Downvoter:小心解释你的downvote? - missingfaktor
@JesperNordenberg,我认为这不是一个很好的理由。 - missingfaktor


减少arity最流行的方式是kind-projector(https://github.com/non/kind-projector)插件也用于猫库。通过启用此插件,您的示例可以转换为:

val a = "a".pure[State[Int, ?]]

注意:默认情况下,将在Dotty中启用此语法。


1
2017-09-20 19:34