2010-06-26 50 views
11

Tôi đã rối tung xung quanh với Scala 2.8 cho vui và cố gắng xác định pimp, thêm phương thức "as" để nhập các nhà xây dựng, cho phép chuyển đổi từ một hàm này sang hàm khác (xin vui lòng bỏ qua một thực tế là tôi không nhất thiết phải đối phó với các functors ở đây). Vì vậy, ví dụ, bạn có thể sử dụng nó như thế này:"không thể tồn tại trừu tượng trên kiểu tham số ..."

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

Vì vậy, đây là những gì tôi đã cố gắng để làm:

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 
    } 
} 

tuy nhiên định nghĩa của naturalTransformations được đánh dấu với lỗi "không thể existentially trừu tượng trên loại tham số G [T] ". Để khắc phục điều này, tôi có thể viết lại naturalTransformations cùng với một lớp học thêm Transformable như vậy:

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) 

và nó xuất hiện để làm việc. Nhưng có vẻ như nỗ lực đầu tiên của tôi nên tương đương, vì vậy tôi tò mò tại sao nó thất bại và thông báo lỗi có nghĩa là gì.

+1

Tôi thường thấy lỗi "Loại thông số trong sàng lọc cấu trúc có thể không đề cập đến một loại trừu tượng được xác định bên ngoài sàng lọc" trong các tình huống tương tự. Sự hạn chế đó liên quan đến cách các kiểu cấu trúc được thực hiện trên JVM với sự phản chiếu, IIRC. http://stackoverflow.com/questions/2685804/scala-parameter-type-in-structural-refinement-may-not-refer-to-an-abstract-type – retronym

Trả lời

10

linh cảm của tôi sẽ được rằng điều này là bởi vì do những điều khoản sau đây trong spec, § 6.11, khối:

Một định nghĩa cục bộ loại kiểu định nghĩa t = T bị ràng buộc bởi các hiện sinh khoản loại t >: T <: T. Đó là một lỗi nếu t mang tham số kiểu.

Và một biểu thức tạo Ví dụ cấu trúc được đánh giá đến một khối, vì vậy


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

là viết tắt của


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

vì thế để đánh giá một biểu thức khối (theo § 6.10 của spec), với giới hạn nói trên. Tại sao hạn chế này là có tôi không biết, tuy nhiên. Lỗi được ném có thể được tìm thấy trong lớp Typers tại this location, dường như xác nhận rằng hạn chế này là nguyên nhân gây ra lỗi mà bạn thấy. Như bạn đã đề cập, mã hóa các chức năng trong một lớp học loại bỏ các hạn chế biểu hiện khối:


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} 

0

Đối với tôi điều này có vẻ giống như một sự đơn giản đối với trường hợp tổng quát: có thể là một biến kiểu mới được tạo ra mỗi khi một khối được tạo ra chụp một số kiểu khởi tạo được khởi tạo với kiểu tồn tại, nhưng điều đó sẽ làm cho các chẩn đoán lỗi khó hiểu hơn.

Cũng lưu ý rằng có một lớp chuyển lời gọi thành INVOKEVIRTUAL nhanh, thay vì gọi phương thức như() bằng cách phản ánh.

Các vấn đề liên quan