亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

強制類型差異

強制類型差異

MM們 2019-07-26 15:14:05
強制類型差異在Scala中,我可以在編譯時強制類型相等。例如:case class Foo[A,B]( a: A, b: B )( implicit ev: A =:= B )scala> Foo( 1, 2 )res3: Foo[Int,Int] = Foo(1,2)scala> Foo( 1, "2" )<console>:10: error: Cannot prove that Int =:= java.lang.String.是否有辦法強制執行A型和B型應該不同的做法?
查看完整描述

3 回答

?
PIPIONE

TA貢獻1829條經驗 獲得超9個贊

借用讓-菲利普的想法,這是有效的:

sealed class =!=[A,B]trait LowerPriorityImplicits {
  implicit def equal[A]: =!=[A, A] = sys.error("should not be called")}object =!= extends LowerPriorityImplicits {
  implicit def nequal[A,B](implicit same: A =:= B = null): =!=[A,B] = 
    if (same != null) sys.error("should not be called explicitly with same type")
    else new =!=[A,B]}     case class Foo[A,B](a: A, b: B)(implicit e: A =!= B)

然后:

// compiles:Foo(1f, 1.0)Foo("", 1.0)Foo("", 1)Foo("Fish", Some("Fish"))// doesn't compile// Foo(1f, 1f)// Foo("", "")

我可能會簡化如下,因為對“作弊”的檢查總是可以避免的。Foo(1, 1)(null)=!=.nequal(null)):

sealed class =!=[A,B]trait LowerPriorityImplicits {
  /** do not call explicitly! */
  implicit def equal[A]: =!=[A, A] = sys.error("should not be called")}object =!= extends LowerPriorityImplicits {
  /** do not call explicitly! */
  implicit def nequal[A,B]: =!=[A,B] = new =!=[A,B]}




查看完整回答
反對 回復 2019-07-27
?
qq_花開花謝_0

TA貢獻1835條經驗 獲得超7個贊

我有一個更簡單的解決方案,它也利用了模糊性,

trait =!=[A, B]implicit def neq[A, B] : A =!= B = null// This pair excludes the A =:= B caseimplicit def neqAmbig1[A] : A =!= A = nullimplicit def neqAmbig2[A] : A =!= A = null

最初的用例,

case class Foo[A,B](a : A, b : B)(implicit ev: A =!= B)new Foo(1, "1")new Foo("foo", Some("foo"))// These don't compile// new Foo(1, 1)// new Foo("foo", "foo")// new Foo(Some("foo"), Some("foo"))

更新

我們可以把這個和我的“神奇的打字技巧”(謝謝@JPP;-)如下:

type ?[T] = T => Nothingimplicit def neg[T, U](t : T)(implicit ev : T =!= U) : ?[U] = nulldef notString[T <% ?[String]](t : T) = t

REPL樣本會話,

scala> val ns1 = notString(1)ns1: Int = 1scala> val ns2 = notString(1.0)ns2: Double = 1.0scala> val ns3 = notString(Some("foo"))ns3: Some[java.lang.String] = Some(foo)scala> val ns4 = notString("foo")<console>:14: error: No implicit view available from 
  java.lang.String => (String) => Nothing.
       val ns4 = notString2("foo")
                            ^


查看完整回答
反對 回復 2019-07-27
?
慕的地10843

TA貢獻1785條經驗 獲得超8個贊

我喜歡Miles Sabin的第一個解決方案的簡單性和有效性,但對我們得到的錯誤沒有多大幫助這一事實有點不滿意:

例如,定義如下:

def f[T]( implicit e: T =!= String ) {}

調度要做f[String]將無法編譯:

<console>:10: error: ambiguous implicit values:
 both method neqAmbig1 in object =!= of type [A]=> =!=[A,A]
 and method neqAmbig2 in object =!= of type [A]=> =!=[A,A]
 match expected type =!=[String,String]
              f[String]
               ^

我寧愿讓編譯器告訴我“T和字符串沒有什么不同”,結果發現,如果添加另一個層次的派生,那么我們就可以將歧義錯誤為隱未發現錯誤。從那時起,我們可以使用implicitNotFound發出自定義錯誤消息的注釋:

@annotation.implicitNotFound(msg = "Cannot prove that ${A} =!= ${B}.")trait =!=[A,B]object =!= {
  class Impl[A, B]
  object Impl {
    implicit def neq[A, B] : A Impl B = null
    implicit def neqAmbig1[A] : A Impl A = null
    implicit def neqAmbig2[A] : A Impl A = null
  }

  implicit def foo[A,B]( implicit e: A Impl B ): A =!= B = null}

現在讓我們試著打電話f[String]:

scala> f[String]<console>:10: error: Cannot prove that String =!= String.
              f[String]
           ^

那好多了。謝謝編譯器。

對于那些喜歡上下文綁定語法糖的人來說,最后一個技巧是可以定義這個別名(基于lambdas類型):

type IsNot[A] = { type λ[B] = A =!= B }

然后我們就可以定義f就像這樣:

def f[T:IsNot[String]#λ] {}

它是否容易閱讀是高度主觀的。在任何情況下,都比寫入完整的隱式參數列表短得多。

更新*為了完整性,這里有一個等價的代碼來表示A的子類型B:

@annotation.implicitNotFound(msg = "Cannot prove that ${A} <:!< ${B}.")trait <:!<[A,B]object <:!< {
  class Impl[A, B]
  object Impl {
    implicit def nsub[A, B] : A Impl B = null
    implicit def nsubAmbig1[A, B>:A] : A Impl B = null
    implicit def nsubAmbig2[A, B>:A] : A Impl B = null
  }

  implicit def foo[A,B]( implicit e: A Impl B ): A <:!< B = null}type IsNotSub[B] = { type λ[A] = A <:!< B }

并表達了A不可兌換為B :

@annotation.implicitNotFound(msg = "Cannot prove that ${A} <%!< ${B}.")trait <%!<[A,B]object <%!< {
  class Impl[A, B]
  object Impl {
    implicit def nconv[A, B] : A Impl B = null
    implicit def nconvAmbig1[A<%B, B] : A Impl B = null
    implicit def nconvAmbig2[A<%B, B] : A Impl B = null
  }

  implicit def foo[A,B]( implicit e: A Impl B ): A <%!< B = null}type IsNotView[B] = { type λ[A] = A <%!< B }




查看完整回答
反對 回復 2019-07-27
  • 3 回答
  • 0 關注
  • 289 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號