2015-07-11 75 views
0

我已經寫了下面的代碼部分來解析表達式中的RDD類型和Float。解析算術表達式由浮子和RDD喜歡:「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中有一個簡單的工作示例。 – 2015-07-12 01:11:01

+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) 

leftright scalaz做你想要的東西 - 他們創建一個左值或右值。你傳遞給 左或右的類型參數用於構造完整類型,因爲值 只提供le英尺或右側類型,但是完整的任一類型都需要另一側(右側/左側)的類型 ,因此還需要傳遞其他類型 。

另一方面,我想你會在後面用 pathxml得到類似的錯誤信息。以類似的方式修復它,除了Right而不是Left

+0

感謝您的幫助。我正在使用Scala組合器分析器。 「.left [..]」在這裏做什麼?因爲num的類型是Float,而pathexml是RDD。 – Rubbic

+0

'.left'來自我最近用過的'scalaz',所以這就是我本能使用的。 stdlib中的'Either'有點雜亂。我重新排序了代碼片段。 – Reactormonk

+0

明白了,在開始時是否需要特定的導入?我得到一個錯誤的「。左側」說:左值不是ParseExp.this.Parser [浮點] – Rubbic