2016-08-17 77 views
3

讓我們假設我有一個高清這需要多個類型參數:在斯卡拉,是否有可能「咖喱」def類型的參數?

def foo[A, B, C](b: B, c: C)(implicit ev: Writer[A])

然而,使用目的是類型參數BC應推斷(基於傳入參數)。調用者只需要明確指定A(例如,由編譯器選擇適當的隱式)。不幸的是,Scala只允許調用者指定所有的類型參數或不指定任何類型參數。從某種意義上說,我想要的類型參數要令行禁止:

def foo[A][B, C]...

有一些技巧在Scala中做到這一點?

(如果我的具體示例沒有完整意義上我很高興與建議,以改善它。)

回答

5

我已經能夠把這事辦成最好的辦法是通過定義持有類curried類型信息然後使用apply方法來模擬函數調用。

我寫這個在這裏 - http://caryrobbins.com/dev/scala-type-curry/

爲了您的具體的例子,你需要把implicit ev: Writes[A]在簽名的apply在簽名foo。這是因爲它會在顯式傳遞隱式參數或隱式調用方法之間造成不明確性。

下面是你的榜樣示例實現 -

object Example { 
    def foo[A]: _Foo[A] = _foo.asInstanceOf[_Foo[A]] 

    final class _Foo[A] private[Example] { 
    def apply[B, C](b: B, c: C)(implicit ev: Writes[A]): Unit = ??? 
    } 

    private lazy val _foo = new _Foo[Nothing] 
} 

然後您可以提供您的類型參數你想討好並傳遞給apply方法如下參數將被推斷。

Example.foo[Int]("bar", new Object) 

如果最終需要指定其他類型的參數,可以通過顯式調用apply這樣做;儘管如此,我從來沒有見過需要這樣做。

Example.foo[Int].apply[String, Object]("bar", new Object) 

如果你不希望使用的中間類型,你也可以使用一個結構類型,這是我在上述討論後;然而,這需要reflectiveCalls和推斷類型簽名,我都喜歡避免這兩種簽名。

+1

寫得很好,很聰明! – Alec