2012-10-25 18 views
9

ai đó có thể giúp tôi hiểu cách sử dụng Kiểu ứng dụng để viết trình phân tích Parsec không? Đây là mã tôi có:Parsec và phong cách áp dụng

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 

nhưng khi tôi cố gắng để biên dịch nó, tôi nhận được như sau:

/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. 

Ý tưởng là tôi muốn cmdParse2 để làm điều tương tự mà cmdParse có, nhưng sử dụng công cụ ứng dụng ... cách tiếp cận của tôi có thể hoàn toàn sai, tôi mới có haskell

+0

Lỗi của bạn như thể bạn đã viết '(++) <$> ...' not '(:) <$> ...'. – huon

+0

xin lỗi, cố định .. tôi đã thử nó với cả hai ++ và: và đã trộn nó lên – Arg

+4

Cuối cùng trong câu hỏi được nghiên cứu kỹ lưỡng, bởi vì câu trả lời là "Thực hiện tốt, lựa chọn âm thanh, thực hiện chính xác, nhưng sửa lỗi loại nhỏ này . " +1 – AndrewC

Trả lời

4

Việc sử dụng ứng dụng của bạn được bật ngay, bạn chỉ có chữ ký không chính xác. Hãy thử:

cmdParse2 :: Parsec String() String 
+1

stupid me, thanks – Arg

+0

chỉ là một câu hỏi nhanh, có thể lấy Text type từ 'many alphaNum' không? vì vậy tôi không luôn luôn đóng gói nó bằng tay nếu tôi muốn sử dụng văn bản thay vì String? – Arg

+0

@Arg 1. Có. Bạn có thể chuyển đổi: '(gói <$> nhiều alphaNum)', nhưng bạn sẽ cần phải chuyển đổi mọi thứ: 'cmdParse3 = cons <$> char '/' <*> (gói <$> nhiều alphaNum)' nhưng viết tốt hơn 'cmdParse4 = pack <$> cmdParse2' , và nó có thể tốt hơn, tùy thuộc vào ứng dụng của bạn để nó cho đến khi kết thúc và làm 'gói <$> myTopLevelParser'. (Bạn cũng có thể quan tâm đến 'Text.Parsec.Text' để thay đổi dữ liệu nguồn.) 2. Tại sao? Bạn đang xây dựng một chuỗi ký tự tại một thời điểm, kết hợp chúng theo cách tốt. 'append' là _O (n) _ cho Văn bản. – AndrewC

4

Cách tiếp cận của bạn có vẻ đúng với tôi, vấn đề là cmdParse2 có loại sai. Nó phải có cùng loại với cmdParse. Nhân tiện, bạn có thể bỏ qua các parens xung quanh char '/' trong trình phân tích cú pháp kiểu ứng dụng.

+0

tuyệt vời, cảm ơn cho các mẹo parens – Arg