2015-07-11 2 views
0

Я написал следующую часть кода для разбора типа RDD и Float в выражении. Для разбора арифметических выражений, состоящий поплавка и РДД нравится: «firstRDD + 2»:Как разобрать два разных типа в одном парсере в Scala?

def term2: Parser[List[Either[Float, RDD[(Int,Array[Float])]]]] = rep(factor2) 
def factor2: Parser[Either[Float, RDD[(Int,Array[Float])]]] = pathxml | num 
def pathxml: Parser[RDD[(Int,Array[Float])]] = pathIdent ^^ {s => pathToRDD(s) } //pathToRDD is a function that gets the path in string and create an RDD from the file inside that path and pathIdent parse to see whether the input string is a path or not 
def num: Parser[Float] = floatingPointNumber ^^ (_.toFloat) 

Теперь я получаю эту ошибку:

[error] type mismatch; 
    [error] found : ParseExp.this.Parser[Float] 
    [error] required: ParseExp.this.Parser[Either[Float,org.apache.spark.rdd.RDD[(Int, Array[Float])]]] 
    [error] def factor2: Parser[Either[Float, RDD[(Int,Array[Float])]]] = pathxml | num 
    [error]                   ^

Я не знаю, как это сделать, за исключением использования " Либо «и не знаю, как решить этот тип несоответствия! Обратите внимание, что если я использую «Любой», он не сможет разобрать RDD.

+0

Что вы используете в классе 'Parser'? Я не могу найти соответствующие документы API. – Reactormonk

+0

Возможно, вы можете использовать тип объединения, определенный в http://milessabin.com/blog/2011/06/09/scala-union-types-curry-howard/. Существует простой рабочий пример на странице https://raw.githubusercontent.com/zalacer/projects-tn/master/UnionTypeDemo/src/tn/UnionTypeDemo.scala. –

+0

@TrisNefzger, это правильный способ сделать это, я согласен. Но Rubbic, похоже, не слишком хорошо знаком с прекрасными сторонами scala, поэтому я не хотел переусердствовать. – Reactormonk

ответ

1

Он хочет Either вместо Float, поэтому вы даете ему Either. Но мы не можем просто создать значение из вывода, потому что парсер работает с функциями, а не значениями.

def num: Parser[Either[Float, RDD[(Int,Array[Float])]]] = floatingPointNumber ^^ (n => Left(n).toFloat) 

и надеюсь, что это сработает. Если этого не произойдет, идти длинный маршрут:

def num: Parser[Either[Float, RDD[(Int,Array[Float])]]] = floatingPointNumber ^^ (n => 
    val res: Either[Float, RDD[(Int,Array[Float])]] = n.toFloat 
    res 
) 

Или маршрут scalaz (вам придется переписать код, чтобы использовать \/ вместо Either:

import scalaz._ 
import Scalaz._ 

def term2: Parser[List[\/[Float, RDD[(Int,Array[Float])]]]] = rep(factor2) 
def factor2: Parser[\/[Float, RDD[(Int,Array[Float])]]] = pathxml | num 
def pathxml: Parser[RDD[(Int,Array[Float])]] = pathIdent ^^ {s => pathToRDD(s) } //pathToRDD is a function that gets the path in string and create an RDD from the file inside that path and pathIdent parse to see whether the input string is a path or not 
def num: Parser[\/[Float, RDD[(Int,Array[Float])]]] = floatingPointNumber ^^ (n => n.left[RDD[(Int,Array[Float])]].toFloat) 

left и right от scalaz делают в значительной степени то, что вы ожидаете - создают левое или правое значение. Аргумент типа, который вы передаете влево или вправо, используется для построения полного типа, поскольку значение предоставляет только файл футов или правого типа, но для полного или любого типа требуется тип другой стороны (справа/слева), поэтому необходимо передать другой тип .

С другой стороны, я думаю, вы получите подобное сообщение об ошибке позже с помощью pathxml. Закрепите его аналогичным образом, за исключением Right вместо Left.

+0

Спасибо за помощь. Я использую парсер Scala combinator. что делает ".left [..]" делать здесь? потому что тип num будет Float, а pathexml - RDD. – Rubbic

+0

'.left' от' scalaz', который я использовал недавно, так что я использовал инстинкт. «Либо» из stdlib немного запутаннее. Я переупорядочил фрагменты кода. – Reactormonk

+0

Понял, нужен ли какой-либо конкретный импорт в начале? Я получаю сообщение об ошибке «.left» говорит: значение left не является членом ParseExp.this.Parser [Float] – Rubbic

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