2011-06-23 16 views
5

私は48時間のチュートリアルで自分自身を書くスキームを試みています。これはかなり難しいです。 私は現在、スキームベクトルを解析する機能を追加する予定の問題に取り組んでいます(セクション3.4のエクササイズ2)。配列を使ったhaskellの構文解析のベクトル

私は、このデータタイプ使用しています:

data LispVal = Atom String     
     | List [LispVal]     
     | Vector (Array Int LispVal) 

を解析するには、私が探している「#(」そして、ベクトルの内容を解析リストにドロップしてにそのリストを変換しようとしています配列。

私は既に持っているが、使用しているリスト解析機能を使用しようとしていますが、上記のLispValリストにスキームリストを解析して、それを通常のリストに戻すのが苦労しています。少なくともそれは私の問題だと私は思う。

lispValtoList :: LispVal -> [LispVal] 
lispValtoList (List [a]) = [a] 

parseVector :: Parser LispVal 
parseVector = do string "#(" 
      vecArray <- parseVectorInternals  
      char ')' 
      return $ Vector vecArray 

parseVectorInternals :: Parser (Array Int LispVal) 
parseVectorInternals = listToArray . lispValtoList . parseList 

listToArray :: [a] -> Array Int a 
listToArray xs = listArray (0,l-1) xs 
    where l = length xs 
この問題を解決する方法について

parseList :: Parser LispVal 
parseList = liftM List $ sepBy parseExpr spaces 

任意のアイデア:

、ここではリストパーサですか? おかげで、 サイモンここ

-edit- は私が手コンパイルエラーです:

Couldn't match expected type a -> LispVal' against inferred type Parser LispVal' In the second argument of (.)' namely parseList' In the second argument of (.)' namely lispValToList . parseList' In the expression: listToArray . lispValToList . parseList

+0

すべてのエラーメッセージが表示されますか?私は 'parseVectorInternals'の定義に型エラーがあると思いますが、コード内の唯一のエラーかどうかはわかりません。また、 'parseVector'の定義の字下げは奇妙です。 –

+0

元の質問を編集してエラーを組み込みました - parseVectorインデントはレンダリングの問題です。実際のコードで問題ありません。 – SimonBolivar

答えて

6

あなたはlispValtoListを提供していないが、私はそれはこれがでしょう、次の型

lispValtoList :: LispVal -> [LispVal] 

を持っていると仮定しますparseLista -> LispValであるとコンパイラに示唆してください。しかし、Parser LispValなので、P String -> [(LispVal,String)]のようなものではありません。

リストに入れる前に、解析された値LispValを抽出する必要があります。 のでparseVectorInternalsは、おそらくあなたは、よりコンパクトな何かを書くことができますが、このコードは自己文書化することを試み

parseVectorInternals = do parsedList <- parseList 
          let listOfLispVal = lispValtoList parsedList 
          return $ listToArray listOfLispVal 

のように見えなければなりません;)lispValtoListはそうプレーンLispValを望んでいるのに対し、

+0

Fraikin - うわー、それは今あります。私は何をしようとしていたかは、私がすべきことを言っているかのようなものだと思います。 lispValToListの目的は、 'LispVal List'からhaskellリストを取得することです。私が(。)演算子を間違って使用していると言っていますか? – SimonBolivar

+1

@SimonBolivarこの場合、 '.parseList'の戻り値が' lispValToList'の引数と一致しないため、(。)演算子が正しくありません。 'parseList'はモナドを返します。これは値を保持するボックスのようなものです。 'do'ブロックの中の' < - 'は値をボックスの外にとり、その値を' lispValToList'に渡すことができます。 (http://learnyouahaskell.com/にはモナドの説明があります) – Alex

+1

@SimonBolivar正確に...問題は合成演算子に由来します。あなたは彼を構成するために 'lispValtoList'を持ち上げる必要があります(持ち上げが分からない場合は' Control.Monad'を見てください)。 John F. Millerが可能性のある修正を行うようです。 –

2

parseListはタイプparser LispValのモナドであります:あなたがしている場合、私は同じ本を読んで8週間前にあった場所

parseVectorInternals = listToArray . lispValtoList `liftM` parseList 

以下は同様にあなたを助ける:

すべてのこれらの行は等価です:あなたは、コードをコンパイルするときに

parseVectorInternals = (listToArray . lispValtoList) `liftM` parseList 
parseVectorInternals = liftM (listToArray . lispValtoList) parseList 
parseVectorInternals = parseList >>= \listLispVal -> return listToArray (lispValtoList listLispVal) 
parseVectorInternals = do 
    listLispVal <- parseList 
    return listToArray (lispValtoList listLispVal) 
+1

ありがとうございます。それはあなたのソリューションにいくつかの問題があるかもしれないと思うが助けになる。まず、 'parseVectorInternals'は' Parser(Array Int LispVal) '型ですので、正しいモナドに戻すには' return'か同等のもの(別の 'liftM'?)が必要です。第2に、最初のコード解は次のようなエラーを出します。_Precedence構文解析エラーは '。'を混ぜることはできません。同じインフィックス式の中の[infixr 9]と[liftM '[infixl 9] _ 私はそのことをどうするべきか分かりません。しかし、 'do'ブロックを持つバージョンは、' return $ 'で最後の行を始めると機能します – SimonBolivar