簡體   English   中英

在Scala中為高級類型鍵入約束

[英]Type constraint for higher-kinded type in Scala

我試圖在scala中為Functors編寫一個通用法則,我可以在scalacheck測試中為許多仿函數重用這種格式。 法律應該由構造函數F [_]和元素類型參數化,比如A.

理想情況下,我會寫這樣的東西:

def functorLaw[A, F[_] :Arbitrary] (fn :Functor[F]) :Prop = forAll { (fa :F[A]) => true }

(我使用true而不是法律機構,因為確切的計算對我的問題無關緊要)

然而,我能破解的最好的方法是將它包裝在一個抽象類中,提供一個隱式生成任意F [A]值的抽象:

abstract class  FunctorSpec[A :Arbitrary, F[_]] extends Properties("foo") {

  implicit def arbitraryFA :Arbitrary[F[A]]
  def functorLaw (fn :Functor[F]) :Prop = forAll { (fa :F[A]) => true } 

}

現在這個有效,但它並不理想。 我需要為每個測試實例化我想要運行的類,並且需要在那里提供任意的ARM函數。 當然,編譯器需要這個函數,但對於許多類型,它們存在應該這樣做的含義(例如對於List [Int])。 然而編譯器將無法猜測這些隱式提供任意FA,所以我需要自己實現,這是非常重復的。 例如:

object IntListFunctorSpec extends FunctorSpec[Int, List] {
  def arbitraryFA :Arbitrary[List[Int]] = Arbitrary(arbitrary[List[Int]])

  ...
}

我認為我不應該告訴scalacheck如何構建int列表。 有什么建議如何更優雅地做到這一點?

我嘗試了更高級別的類型邊界的其他問題,我無法弄清楚如何使用它們,即使它們聽起來很接近。 所以我想我會問。

你的嘗試不起作用的原因是因為你有一種不匹配。 下列:

def functorLaw[A, F[_] :Arbitrary] (fn :Functor[F]) :Prop = forAll { (fa :F[A]) => true }

只是一個語法糖:

def functorLaw[A, F[_]] (fn :Functor[F])(implicit evidence: Arbitrary[F]) :Prop = forAll { (fa :F[A]) => true }

所以從本質上講,問題是你的方法需要一個類型為Arbitrary[F]的隱式值,其中F是一個高階類型( F[_] ),但這沒有意義,因為Arbitrary沒有采用更高階的類型:

// T is a first order type, it has the kind *
// Simply put, it is not a type constructor
class Arbitrary[T]

為了讓您的代碼按原樣編譯(並且有意義), Arbitrary必須聲明如下:

// T is a type constructor, it has the kind * -> *
class Arbitrary[T[_]]

現在是如何解決它。 在你的情況下,你想要的實際任意值是F[A]類型,而不是F (這應該不用說,因為它不是具體的類型,而是一個類型構造函數),所以隱含的你需要的是Arbitrary[F[A]]類型Arbitrary[F[A]]

def functorLaw[A, F[_]] (fn :Functor[F])(implicit arb: Arbitrary[F[A]]) :Prop = forAll { (fa :F[A]) => true }

並且因為F[A]不出現在類型參數列表中(有AF ,而不是F[A] ),所以不能使用“上下文綁定”語法糖,我們不得不使用顯式(!)隱式參數列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM