2012-12-17 24 views
11

Các ý chính sau đây có mã cho một ý tưởng tôi đang chơi vớiIssue giải quyết arity của args chức năng để lái xe xử lý danh sách, sử dụng hình thù

package com.test1 

import scala.language.implicitConversions 
import shapeless._ 
import FromTraversable._ 
import Traversables._ 
import Nat._ 
import Tuples._ 

trait ToArity[P, N <: Nat] 

object ToArity { 
    implicit def prod1[P <: Product1[_]] = new ToArity[P, _1] {} 
    implicit def prod2[P <: Product2[_, _]] = new ToArity[P, _2] {} 
    // ad nauseum... 
} 

trait SizedHListAux[A, N <: Nat, T <: HList] 

object SizedHListAux { 
    implicit def base[A, H <: HList] = new SizedHListAux[A, _0, HNil] {} 
    implicit def induct[A, H <: HList, N <: Nat, P <: Nat](implicit r: PredAux[N,P], k: SizedHListAux[A, P, H]) = new SizedHListAux[A, N, A :: H] {} 
} 

trait SomeFun { 
    type Result 
    def apply(): Result 
} 

// I want to abstract over A, the contained type in the List 
// over P the Product type which is the arg notably its arity 
// This means we need to recover arity of the Product type and render it in value space 
// and also means that we need to compute the type of the intermediate HList 
object SomeFun { 
    def produce(m: SomeFun): m.Result = m() 

    implicit def fromF1[T, A, P <: Product, N <: Nat, H <: HList](f1: (P => T, List[A]))(implicit k: ToArity[P, N], toI: ToInt[N], l: SizedHListAux[A, N, H], toHL: FromTraversable[H], tp: TuplerAux[H, P]) = 
    new SomeFun { 
     type Result = (T, List[A]) 
     def apply(): Result = { 
     val (f, as) = f1 
     val (ts, rest) = (as.take(toI()), as.drop(toI())) 
     f((toHL(ts).get).tupled) -> rest 
     } 
    } 
    // Debug Arity checker 
    def printArity[P <: Product, N <: Nat](p: P)(implicit k: ToArity[P, N], toI: ToInt[N]) = println("Arity: " + toI()) 
} 

object Test { 
    val thedata = List("foo", "bar", "baz", "bob") 
    val tfn = (x: (String, String)) => println("%s and %s".format(x._1, x._2)) 
    def foo = SomeFun.printArity("a" -> "b") 
    //def doit = SomeFun.produce((tfn, thedata)) // Adding this line does not compile 
} 

Ý tưởng là bạn sử dụng arity lập luận của một chức năng, trong trường hợp này arity của một loại sản phẩm, để phân tích cú pháp của một danh sách liên quan [A]. Loại giống như sử dụng băng dính để bóc lớp graphene khỏi graphit, tức là loại chức năng kéo mọi thứ ra khỏi danh sách. Đây chỉ là một phác thảo sử dụng một loại duy nhất, nhưng tôi tưởng tượng nó có thể được khái quát hóa. Khía cạnh quan trọng là bản thân các hàm không biết về xử lý Danh sách.

Tuy nhiên ... khái niệm có vẻ thất bại khi cố gắng giải quyết ToArity [P, N] ngầm định. Ngày ToArity riêng của nó là resolvable bằng chứng là printArity().

Ai đó có thể làm sáng tỏ một số lý do tại sao điều này không thể giải quyết được trong ngữ cảnh của fromF1? Có phải là nó không thể giải quyết tất cả các implicit phụ thuộc và sau đó đăng ký lỗi với đầu tiên, tức là một N không thể được tìm thấy để đáp ứng ToArity, ToInt và SizedHListAux?

Trả lời

5

Cập nhật: Tôi vừa xem bản chỉnh sửa của bạn, điều đó có nghĩa là bạn đã giải quyết được vấn đề được ghi chú trong vài đoạn đầu tiên ở đây, nhưng tôi hy vọng phần còn lại sẽ hữu ích.

Vấn đề là dụ SizedHListAux của bạn không được suy ra:

scala> implicitly[SizedHListAux[String, _1, String :: HNil]] 
<console>:25: error: could not find implicit value for parameter e... 

May mắn thay đây là một sửa chữa dễ dàng:

object SizedHListAux { 
    implicit def base[A] = new SizedHListAux[A, _0, HNil] {} 
    implicit def induct[A, H <: HList, N <: Nat, P <: Nat](implicit 
    r: PredAux[N, P], 
    k: SizedHListAux[A, P, H] 
) = new SizedHListAux[A, N, A :: H] {} 
} 

Tôi vừa mới loại bỏ các tham số R <: PredAux[N, P] loại và gõ r thích hợp. Tôi cũng đã xóa thông số loại không được sử dụng H trên base, mặc dù nó không gây ra sự cố — nhưng nó không hoạt động.

Đó là gần như tất cả bây giờ tất cả các trường hợp cho fromF1 được suy ra:

scala> SomeFun.fromF1((tfn, thedata)) 
res0: SomeFun{type Result = (Unit, List[String])} = [email protected] 

Bạn tôi vẫn sẽ không có được một cái nhìn từ các loại (tfn, thedata) để SomeFun, mặc dù. Hãy xem xét các ví dụ đơn giản sau:

scala> trait Foo 
defined trait Foo 

scala> trait Bar[A, B] 
defined trait Bar 

scala> implicit def toInt[F <: Foo, X](f: F)(implicit ev: Bar[F, X]) = 42 
toInt: [F <: Foo, X](f: F)(implicit ev: Bar[F,X])Int 

scala> implicit object fooBar extends Bar[Foo, String] 
defined module fooBar 

scala> toInt(new Foo {}) 
res0: Int = 42 

scala> implicitly[Foo => Int] 
<console>:12: error: No implicit view available from Foo => Int. 
       implicitly[Foo => Int] 

Vì vậy, mặc dù chúng ta có một phương pháp ngầm trong phạm vi đó sẽ làm thay đổi một Foo thành một Int, mà X gây ra vấn đề cho các trình biên dịch khi nó cố gắng để tìm một cái nhìn từ Foo để Int .

Trong trường hợp của bạn, tôi sẽ tránh giới hạn này bằng cách bỏ qua doanh nghiệp SomeFun và có phương thức mất (P => T, List[A]) và trả lại (T, List[A]).

Tôi cũng sẽ quan sát rằng cả hai ToAritySizedHListAux dường như không cần thiết, vì bạn có thể thu thập các bằng chứng tương tự với TuplerAux, LengthAuxLUBConstraint.Ví dụ:

import shapeless._ 

trait SomeFun { 
    type Result 
    def apply(): Result 
} 

implicit def fromF1[T, A, P <: Product, N <: Nat, H <: HList](
    f1: (P => T, List[A]) 
)(implicit 
    tp: TuplerAux[H, P], 
    hl: LengthAux[H, N], 
    toHL: FromTraversable[H], 
    allA: LUBConstraint[H, A], 
    toI: ToInt[N] 
) = new SomeFun { 
    type Result = (T, List[A]) 
    def apply(): Result = { 
    val (f, as) = f1 
    val (ts, rest) = (as.take(toI()), as.drop(toI())) 
    f((toHL(ts).get).tupled) -> rest 
    } 
} 

Và sau đó:

val tfn = (x: (String, String)) => println("%s and %s".format(x._1, x._2)) 
val thedata = List("foo", "bar", "baz", "bob") 
val sf = fromF1((tfn, thedata)) 

Và cuối cùng:

scala> sf() 
foo and bar 
res2: (Unit, List[String]) = ((),List(baz, bob)) 

Không gây phiền nhiễu prodN soạn sẵn cần thiết.

+0

AH! Làm cho cảm giác bây giờ, cảm ơn cho các con trỏ về việc sử dụng các thành phần tiêu chuẩn Shapeless ... đã hy vọng tôi có thể gián tiếp thông qua SomeFun để trừu tượng trên các sản phẩm khác nhau() biến thể nhưng bây giờ có vẻ như một bước quá xa. – dconlon

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