2015-02-11 13 views
7

Mam problem z niejawnymi konwersjami i funkcjami wyższego rzędu. Wydaje się, że niejawne konwersje funkcji na funkcję drugiego rzędu działają tylko wtedy, gdy funkcja konwersji ma co najmniej dwa parametry.Niejawna konwersja funkcji do funkcji drugiego rzędu działa tylko wtedy, gdy funkcja konwersji ma co najmniej dwa parametry.

Works:

implicit def conv(foo: Integer => String): String => String = null 

nie działa:

implicit def conv(foo: Integer => String): String => String => String = null 

działa:

implicit def conv(foo: (Integer, Integer) => String): String => String => String = null 

Pełny przykład z punktu awarii:

{ 
    implicit def conv(foo: Integer => String): String => String = null 

    def baadf00d(foo: Integer): String = null 

    def deadbeef(foo: String => String) = null 

    deadbeef(conv(baadf00d)) 

    deadbeef(baadf00d) 
} 

{ 
    implicit def conv(foo: Integer => String): String => String => String = null 

    def baadf00d(foo: Integer): String = null 

    def deadbeef(foo: String => String => String) = null 

    deadbeef(conv(baadf00d)) 

    deadbeef(baadf00d) // <-------- DOES NOT COMPILE! 
} 

{ 
    implicit def conv(foo: (Integer, Integer) => String): String => String => String = null 

    def baadf00d(foo: Integer, bar: Integer): String = null 

    def deadbeef(foo: String => String => String) = null 

    deadbeef(conv(baadf00d)) 

    deadbeef(baadf00d) 
} 

Czego mi brakuje?

Dzięki!

+2

Wygląda niejawny rozdzielczości brodawki w Scali do mnie. Która wersja Scala to jest? – gzm0

Odpowiedz

-1
implicit def conv1(a: Function1[Int, String]): Function2[String, String, String] = null 
def baadf00d1(i: Int): String = null 
def deadbeef1(arg: Function2[String, String, String]) = null 
deadbeef(baadf00d) // compiles 

To konwersja między A => B i Function1[A,B] że nie dzieje.

Ponadto istnieje Function wpisz Predef - zauważyć różnice typu tutaj:

scala> val f1: Function[Int, Int] = null 
f1: Function[Int,Int] = null 

scala> val f2: Function1[Int, Int] = null 
f2: Int => Int = null 

scala> :type f1 
Function[Int,Int] 

scala> :type f2 
Int => Int 

To aliasem Function1, ale z różnych granicach typu (jak wskazano w komentarzach poniżej).

+0

Możesz nawet przypisać 'baadf00d' do wartości val za pomocą' val baadf00d2 = baadf00d _', a następnie działa –

+0

: type i: kind traktuj je jednolicie w REPL, co sprawia, że ​​wygląda jeszcze dziwniej. –

+2

from Predef.scala "type Funkcja [-A, + B] = Function1 [A, B]" – zarthross

3
implicit def conv(foo: Integer => String): String => String => String = ??? 

    def baadf00d(i: Integer): String = ??? 
    def goodf00d: Integer => String = _ => ??? 

    def deadbeef(foo: String => String => String) = ??? 

    deadbeef(conv(baadf00d)) 

    deadbeef(baadf00d) // <-------- DOES NOT COMPILE! 
    deadbeef(goodf00d) // <-------- COMPILE! 
    // ¯\_(ツ)_/¯ 

Problem polega na tym, jak niejawne konwersje działają na Scali oraz na fakt, że Scala ma funkcje curry i uncurry.

To jest coś, co powinno działać, ale nie działa i prawdopodobnie jest kolejnym błędem kompilatora (przygotuj się na spotkanie z wieloma innymi użytkownikami, gdy będziesz coraz częściej używać Scala).

EDIT: Co do ostatniego przykładu

implicit def conv(foo: (Integer, Integer) => String): String => String => String = null 

def baadf00d(foo: Integer, bar: Integer): String = null 

def deadbeef(foo: String => String => String) = null 

To dlatego, że definicje funkcji są zgodne. Konw oczekuje, że funkcja (Int, Int) => String i normalna definicja metody (uncurried) w scala, jak zdefiniowano baadf00d, zamienia się w tę funkcję.

Na przykład, funkcja:

def f(a: Int, b: Int): String 

Gets przekształcony w

(Int, Int) => String 

zauważyć, że 2 Ints są tupled! To nie jest takie samo jak:

Int => Int => String 

Jeśli było przedefiniowanie baadf00d do:

def baadf00d: Integer => Integer => String = _ => _ => ??? 

Ten kod nie będzie kompilować, ponieważ baadf00d jest „inny”, mimo że robi ta sama rzecz.

Aby uzyskać więcej informacji, należy spojrzeć na definicję obiektów:

Function1, Function2, Function3 .... 

http://www.scala-lang.org/api/current/#scala.Function2

+0

OK, więc powodem, dla którego druga konwersja nie działa, jest po prostu błąd kompilatora ... – user3612643

+0

Tak. W Scali 'baadf00d' i' goodf00d' powinny zostać zamienione na '(Int) => String' i' Int => String'. Teraz te rzeczy powinny być takie same, ale z jakiegoś powodu, Implicit Resolution uważa, że ​​są różne. Fakt, że możesz przekazać 'baadf00d' do' conv' dowodzi, że są one takie same, to tylko ukryta rozdzielczość jest zbyt głupia, aby to rozgryźć. – Nacht

Powiązane problemy