2012-05-09 7 views
12

最近、私は分散エイリアスがタイプエイリアスで使用できることに気付きました。ここでPredefからの例です:タイプエイリアス内の分散アノテーション

type Function[-A, +B] = Function1[A, B] 

そして、それを使用することができるところ私は、と思うようになりました。明らかに、分散を反対に変えることはできません。また、不変型を共変または反変として振る舞わせることもできません。 (少なくとも、コンパイラはそれと主張しません)コンパイラは、この

scala> type BrokenFunc[+T, -R] = Function1[T, R] 
<console>:7: error: covariant type T occurs in contravariant position in type 
    [+T, -R]T => R of type BrokenFunc 

のように、エラーがスローされます。しかし、あなたはいくつかのバリアント型は不変のように動作することができます。だから、私はList

scala> type InvList[T] = List[T] 
defined type alias InvList 

の不変のバージョンを作ってみました。しかし、この新しい不変Listはまだそれが元共変バージョンだだけのように振る舞う:

scala> val l: InvList[String] = List("foo") 
l: InvList[String] = List(foo) 

scala> val anyList: InvList[Any] = l 
anyList: InvList[Any] = List(foo) 

だから、私は何をしないのですが?型別名の分散注釈の目的は何ですか?あなたは、元の型とは異なる、分散注釈付きの型エイリアスの例を挙げることができますか?

答えて

8

だから、私は確かに知っていないが、私は可能性を提供するつもりです:抽象型は、よりリラックスした分散を持つように定義されている場合、これは一度(DomainImplのように)知られ尊敬されています説明。

Scalaの型エイリアスはかなり弱いです。彼らは新しい型を完全に作成するのではなく、古い型(および新しいパスに依存する型)を書く新しい方法だけです。これは、あなたが

type InvList[T] = List[T] 

InvList[T]を書き込みを定義した場合、それは正確にあなたがList[T]を書いたかのようであることを意味します。その理由はInvList[Int] <: InvList[Any]です。書き直したので、これはちょうどList[Int] <: List[Any]です。私は実際に "弱い" Scala型のエイリアスがどのようになっているのか正確には分かりません...パス依存型のためにHaskellより少し強くなりますが、クラス宣言よりも弱いです。他の誰かがさらに説明するかもしれない。

なぜ、それを無視して型を書き換えようとしているのであれば、分散注釈をそこに置くことができるのはなぜですか?これはタイプメンバーのためのものです。あなたは

trait A { type F[+T] } 

を言うと、あなたがから、この文からと、

trait B extends A { type F[+T] = List[T] } 

なく

trait C extends A { type F[T] = Function[T,T] } 

を許可するか、そのような実装は、+T分散に適合することを要求することができるようなものですScala Language Spec S4.3

タイプコンストラクタの宣言は、コンクリートタイプ に追加の制限を課します。境界LとUの他に、型パラメータ句 型コンストラクタ(§3.5.2)の適合 によって支配されるように、上位境界および分散を課すことができます。

+0

私はまた、彼らは、彼らが(別名)れているものであるので、その型の別名は、「弱い」と言うではないでしょう。私はそれは素晴らしい機能だと思うし、それはJavaで全く欠けているのです。どのくらいの頻度私はすべての必要な結果を伴う専用のクラスを定義することなく、地図<リスト、地図<文字列、ダブル>>のようなもののために短い名前を持っていたかったです。 –

+0

@ThiporKongのWRTポイント1は、私がREPLでそれを試してみましたが、それがOKに動作し、私はそれは良いことだと思います。 wrtポイント2、あなたが正しいです、 "弱い"は誤解を招く言葉かもしれませんが、これまで私がこれまで使用してきた言葉です(例えば、Cのtypedef、Haskellの型名エイリアス)。弱いということは悪い意味ではありません。しかし、私が使用できるより良い言葉がありますか? – Owen

+0

再。機能 - はい、もちろん、あなたは正しいです。私が見たことが分からない。 –

2

抽象型が宣言されている場合(Domainなど)、不変量が適用されます。

trait Domain { 
    type InvList[T] 

    val xi: InvList[Int] 
    private val xa: InvList[Any] = xi // won't compile 
} 

class DomainImpl extends Domain { 
    type InvList[T] = List[T] 

    val xi: InvList[Int] = List(1) 
    private val xa: InvList[Any] = xi // will compile 
}