"لا يمكن أن يكون مجردة الوجودية على نوع المعلمة ..."

StackOverflow https://stackoverflow.com/questions/3122398

سؤال

كنت أتجول مع Scala 2.8 من أجل المتعة وأحاول تحديد أ عرسة الذي يضيف طريقة "AS" لتكتب المُنشئين ، والسماح بالتحويل من فونكتور إلى آخر (يرجى التغاضي عن حقيقة أنني لا أتعامل بالضرورة مع المسلسلات هنا). على سبيل المثال ، يمكنك استخدامه مثل هذا:

val array:Array[T]
val list:List[T] = array.as[List]

إذن هذا ما حاولت فعله:

object Test {
    abstract class NatTrans[F[_], G[_]] {
        def convert[T](f:F[T]):G[T]
    }

    implicit def array2List:NatTrans[Array, List] = new NatTrans[Array, List] { 
        def convert[T](a:Array[T]) = a.toList
    }

    // this next part gets flagged with an error
    implicit def naturalTransformations[T, F[_]](f:F[T]) = new {
        def as[G[_]](implicit n:NatTrans[F, G]) = n convert f
    }
}

لكن تعريف naturalTransformations تم وضع علامة مع الخطأ "لا يمكن تجريد الوجوه على النوع المعلمات G [t]. لإصلاح هذا ، يمكنني إعادة كتابة naturalTransformations جنبا إلى جنب مع فئة إضافية Transformable مثل ذلك:

class Transformable[T, F[_]](f:F[T]) {
    def as[G[_]](implicit n:NatTrans[F, G]) = n convert f
}

implicit def naturalTransformations[T, F[_]](f:F[T]) = new Transformable[T, F](f)

ويبدو أنه يعمل. ولكن يبدو أن محاولتي الأولى يجب أن تكون مكافئة ، لذلك أنا فضولي لماذا فشلت وما تعنيه رسالة الخطأ.

هل كانت مفيدة؟

المحلول

سيكون حدسي هو أن هذا بسبب العبارات التالية في المواصفات ، الفقرة 6.11 ، كتل:

يرتبط نوع تعريف النوع المحدد محليًا T = T بنوع البند الوجودي T>: T <: T. إنه خطأ إذا كان T يحمل معلمات النوع.

ويتم تقييم تعبير إنشاء مثيل هيكلي إلى كتلة ، لذلك


new {def greet{println("hello")}}

هو اختصار ل


{ class anon$X extends AnyRef{ def greet = println("hello") }; new anon$X }

لذلك يتم تقييمه لتعبير كتلة (وفقًا للمادة 6.10 من المواصفات) ، مع القيود المذكورة أعلاه. لماذا هذا التقييد موجود لا أعرف ، ولكن. يمكن العثور على الخطأ الذي تم إلقاؤه في فئة typers على هذا الموقع, ، والذي يبدو أنه يؤكد أن هذا التقييد هو سبب الخطأ الذي تراه. كما ذكرت ، فإن ترميز الوظيفة في فئة يزيل تقييد التعبير كتلة:


scala> class N[M[_]]
defined class N

scala> class Q { def as[M[_]](n:N[M]) = null}
defined class Q

scala> new { def as[M[_]](n:N[M]) = null}       
:7: error: can't existentially abstract over parameterized type M
       new { def as[M[_]](n:N[M]) = null}

نصائح أخرى

بالنسبة لي ، يبدو هذا وكأنه بساطة ضد حالة عمومية: يمكن أن يكون هناك متغير نوع جديد تم إنشاؤه في كل مرة يتم فيها إنشاء كتلة لالتقاط بعض منشئ النوع الذي تم إنشاءه بنوع وجودي ، لكن هذا من شأنه أن يجعل تشخيصات الأخطاء أكثر صعوبة في الفهم.

لاحظ أيضًا أن وجود فصل يحول المكالمة إلى invokevirtual سريعًا ، بدلاً من التذرع كما() طريقة عن طريق التفكير.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top