2013-09-27 3 views
1

В настоящее время я пытаюсь решить some Scala problem set для ознакомления с языком. Я застрял с проблемой 11, где мое решение не будет компилироваться. Мой вопрос: почему это незаконно в Scala?Тип вывода с функциональными литералами

def countPackSingle[A](list: List[A]): List[Any] = { 
    pack(list) map {ls => { 
    case head :: Nil => head 
    case head :: tail => List(tail.size + 1, head) 
    }} 
} 

IntelliJ счастлив об этом определении, но компилятор жалуется:

отсутствует параметр типа для расширенной функции
типов аргументов анонимной функции должны быть полностью известен. (SLS 8.5)

Ожидаемый тип:?

pack(list) map {ls => { 
        ^

Я не получить то, что это сообщение пытается мне сказать. Может ли компилятор scala не выводить тип ls? Когда я укажу тип ls: List[A], проблема остается.

В этом случае: Почему я могу указать тип аргумента ls при использовании фигурных скобок { }, но не при использовании круглых скобок ()? До сегодняшнего дня я ищу хороший ресурс, объясняющий разницу в Scala. До сих пор я считал, что он делает только real difference when using the literals to create parial functions via `case и в некоторых других редких случаях.

Спасибо за помощь!

ответ

4

Эта структура:

{ 
    case head :: Nil => head 
    case head :: tail => List(tail.size + 1, head) 
} 

является синтаксическим сахаром для частичной функции, поэтому компилятор бросает вам это сообщение, scalac думает, что вы пытаетесь сделать PartilFunction[List[A], List[A]]. Чтобы устранить эту проблему, у вас есть три пути:

1) в комплекте это шаблон соответствия конструкции:

pack(list) map { ls => ls match { 
    case head :: Nil => head 
    case head :: tail => List(tail.size + 1, head) 
    } 
} 

2) Используйте подчеркивающие синтаксис:

pack(list) map { _ match { 
    case head :: Nil => head 
    case head :: tail => List(tail.size + 1, head) 
    } 
} 

который на самом деле то же самое. Теперь, если вы хотите, вы можете приписать тип для ls, но scala может успешно вывести его.

3) Используйте встроенный синтаксис:

pack(list) map { 
    case head :: Nil => head 
    case head :: tail => List(tail.size + 1, head) 
} 

Это возможно потому, что PartialFunction является подклассом Function, поэтому можно использовать частичную функцию непосредственно вместо простой функции.

И у вас нет никакого смысла в результате типа List[Any]. 1) этот тип не очень хорош, потому что вы потеряете всю информацию о вашем типе и 2) вы не являетесь tailrecursive, поэтому можете отбросить его и позволить скаляру вывести его для вас

+0

@raphw Вот что компилятор пытается вам рассказать , отметьте [SLS 8.5] (http://www.scala-lang.org/files/archive/nightly/pdfs/ScalaReference.pdf) – 4lex1v

+0

Во втором взгляде: не должен ли первый литерал частичной функции приводить к 'PartialFunction [ Список [A], Any] 'type? И не должен ли тип возврата быть «List [Any]» из-за этого? –

+0

@raphw Я не пытался решить эту проблему, так что это зависит от вашей функции 'pack' и в чем заключается задача: мой ответ был в общей теории, в вашем случае это может быть иначе, поэтому лучше отказаться от некоторых явных типов и пусть это сказывается на вас. – 4lex1v

Смежные вопросы