[英]Scala Type Parameter with Either
class OptionLikeMatcher[F[_], T, U](typeName: String, toOption: F[T] => Option[U]) extends Matcher[F[T]] { ... }
case class RightMatcher[T]() extends OptionLikeMatcher[({type l[a]=Either[_, a]})#l, T, T]("Right", (_:Either[Any, T]).right.toOption)
case class LeftMatcher[T]() extends OptionLikeMatcher[({type l[a]=Either[a, _]})#l, T, T]("Left", (_:Either[T, Any]).left.toOption)
有人可以用類型參數解釋他們試圖在這里實現什么嗎? 當用於RightMatcher
和LeftMatcher
時, toOption: F[T] => Option[U]
參數有什么類型?
它來自 Scala Specs2 庫。
讓我們首先在這里解決最復雜的類型構造函數:
({type l[a]=Either[_, a]})#l
是編碼類型 lambdas的原始方式。 它可以更簡潔地寫成
Either[_, ?]
與 kind-projector 或 as
[X] =>> Either[_, X]
在 Scala 3. 它基本上只是選擇Either
的右側參數作為相關參數,並將左側參數替換為通配符。
現在, OptionLikeMatcher
的三個類型參數是:
F[_]
- 被匹配事物的類型構造函數; 預計它的行為“有點類似” Option
,即應該有某種方法可以從中獲取Option
。T
是插入F
類型構造函數的類型; F[T]
一起給出了匹配的類型。U
可以被認為是T
的“輕微擾動”版本; 它捕獲與T
基本相同的信息,但在將F[T]
轉換為Option[U]
時允許一些受控的草率(否則,如果需要F[T] => Option[T]
,那實際上是就像要求一個非常嚴格的結構,稱為自然變換F ~> Option
,在這種情況下可能過於嚴格)。 將它們放在一起給出了RightMatcher
:
F[A] = Either[_, A]
- 即選擇Either
的右參數,忽略左參數RightMatcher
中的T
綁定到OptionLikeMatcher
中的T
OptionLikeMatcher
中的U
也綁定到RightMatcher
中的T
,即此處不使用“輕微擾動” T
的可能性, OptionLikeMatcher
中的T
和U
都由相同類型實例化。 因此, toOption
中的RightMatcher
具有類型Either[_, T] => Option[T]
。 (_:Either[Any, T]).right.toOption
符合Either[_, T] => Option[T]
,因為Any
出現在 Either 內的協變 position 中,並且Either
Either[Any, T]
出現在function 類型內的逆變 position,因此Either[Any, T] => Option[T]
是Either[_, T] => Option[T]
的子類型,因為它的輸入類型更嚴格,而且它可以在需要Either[_, T] => Option[T]
的任何地方使用。
話雖這么說,我找不到任何不屬於F[T]
形狀的F
應用程序(在OptionLikeMatcher
和OptionLikeChekedMatcher
中都沒有),因此它們似乎將輸入類型拆分為類型構造函數F
和類型參數T
,稍后僅將它們用作不可分割的單元F[T]
。 也許這是在從一些更復雜的構造重構之后遺留下來的。
toOption: F[T] => Option[U]
參數用於RightMatcher
和LeftMatcher
時有什么類型
也許具體的演練會有所幫助。 讓我們考慮RightMatcher[Int]()
,我們將類型參數T
實例化為Int
。 這給了我們
F = ({type l[a]=Either[_, a]})#l
T = Int
U = T = Int
並將上述類型實例插入
toOption: F[T] => Option[U]
我們得到
toOption: (({type l[a]=Either[_, a]})#l)[Int] => Option[Int]
這簡化為
toOption: Either[_, Int] => Option[Int]
讓我們對LeftMatcher[String]()
再做一次練習。 我們有
F = ({type l[a]=Either[a, _]})#l
T = String
U = T = String
並將上述類型實例插入
toOption: F[T] => Option[U]
我們得到
toOption: (({type l[a]=Either[a, _]})#l)[String] => Option[String]
這簡化為
toOption: Either[String, _] => Option[String]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.