2012-10-25 15 views
9

Parsecパーサーを書くためのApplicativeスタイルの使い方を教えてもらえますか?ParsecとApplicativeスタイル

module Main where 
import Control.Applicative hiding (many) 
import Text.Parsec 
import Data.Functor.Identity 
data Cmd = A | B deriving (Show) 

main = do 
    line <- getContents 
    putStrLn . show $ parseCmd line 

parseCmd :: String -> Either ParseError String 
parseCmd input = parse cmdParse "(parser)" input 

cmdParse :: Parsec String() String 
cmdParse = do 
    slash <- char '/' 
    whatever <- many alphaNum 
    return (slash:whatever) 

cmdParse2 :: String -> Parsec String() String 
cmdParse2 = (:) <$> (char '/') <*> many alphaNum 

をしかし、私はそれをコンパイルしようとすると、私は以下の取得:

/home/tomasherman/Desktop/funinthesun.hs:21:13: 
    Couldn't match expected type `Parsec String() String' 
       with actual type `[a0]' 
    Expected type: a0 -> [a0] -> Parsec String() String 
     Actual type: a0 -> [a0] -> [a0] 
    In the first argument of `(<$>)', namely `(:)' 
    In the first argument of `(<*>)', namely `(:) <$> (char '/')' 
Failed, modules loaded: none. 

アイデアは私がcmdParse2がcmdParseと同じことをしたいということですが、使用してこれは私が持っているコードです。アプリケーションのもの...私のアプローチはおそらく完全に間違っている、私はhaskellに新しいです

+0

あなたの誤差がある '(++)<$> ...' 'ない(:) <$>を...'。 – huon

+0

申し訳ありませんが、私は++との両方で試していました:そしてそれを混ぜ合わせました – Arg

+4

答えが「うまくいきました、健全な選択、正しく行われましたが、このマイナータイプのエラーを修正するので、 " +1 – AndrewC

答えて

4

あなたのアプリケーションの使用状況が表示されていますが、不正な署名があります。試してみてください:あなたが書かれたかのように

cmdParse2 :: Parsec String() String 
+1

愚かな私、ありがとう – Arg

+0

ただの質問です。「多くのalphaNum」からタイプテキストを得ることは可能ですか?文字列の代わりにテキストを使用したい場合は、手動でパックする必要はありませんか? – Arg

+0

@Arg 1.はい。 'cmdParse3 = cons <$> char '/' <*>(パック<$>多くのalphaNum)'を変換する必要があります。 'cmdParse4 = pack <$> cmdParse2'あなたのアプリケーションによっては最後まで残しておき、 'pack <$> myTopLevelParser'を実行する方が良いかもしれません。 ( 'Text.Parsec.Text'に興味があり、ソースデータも変更することができます。)2.なぜですか?一度に文字列を作成し、それらを組み合わせて良い方法です。とにかく 'append'は_O(n)_です。 – AndrewC

4

私の考え方は正しいと思われますが、問題はcmdParse2が間違ったタイプです。それはcmdParseと同じタイプでなければなりません。ちなみに、アプリケーションスタイルのパーサーでは、char '/'の括弧を省略することができます。

+0

クール、謝辞のお返事ありがとう – Arg

関連する問題