2013-08-18 30 views
5

Tôi đang cố gắng tìm hiểu Parsec và đang cố gắng phân tích một địa chỉ email đơn giản. Tôi đã thử mã sau đây. Sản lượng dự kiến ​​của tôi là toàn bộ địa chỉ email dưới dạng chuỗi. Nhưng khi tôi chạy mã, tôi chỉ nhận được ".com" Có thể somene xin vui lòng cho tôi biết whats đang xảy ra?Tai họa Haskell Parsec

{-# LANGUAGE NoMonomorphismRestriction #-} 

import Text.Parsec 
import Control.Applicative hiding ((<|>)) 

email = many1 alphaNum 
    *> char '@' 
    *> many1 alphaNum 
    *> string ".com" 

emailstr = parse email "" "[email protected]" 

Trả lời

12

Các loại chữ ký cho *> nói nó trả về kết quả từ thứ hai phân tích cú pháp, và ném đi những kết quả từ phân tích cú pháp đầu tiên. Do đó, email chỉ trả lại kết quả từ trình phân tích cú pháp cuối cùng trong chuỗi.

Những gì bạn có thể muốn là một cái gì đó giống như

email = 
    stitch 
    <$> many1 alphaNum 
    <*> char '@' 
    <*> many1 alphaNum 
    <*> string ".com" 

này chạy bốn parsers và chuyển kết quả của từng như một cuộc tranh cãi để stitch. Nếu bạn viết triển khai phù hợp cho stitch:

stitch a b c d = a ++ [b] ++ C++ d 

thì bạn sẽ lấy lại chuỗi của mình.

Chú ý rằng vào thời điểm này, bạn cũng có thể đặt tên người dùng và miền vào các lĩnh vực riêng biệt của một cấu trúc dữ liệu hoặc một cái gì đó:

data Email = Email {username, domain :: String} 

email = 
    Email 
    <$> many1 alphaNum 
    <* char '@' 
    <*> ((++) <$> many1 alphaNum <*> string ".com") 

Bây giờ phân tích cú pháp của bạn trả về một cấu trúc Email chứ không phải chỉ là một chuỗi đồng bằng. Đó có thể không phải là những gì bạn đang theo dõi, nhưng nó thể hiện cách viết một trình phân tích cú pháp phức tạp hơn.

Tất cả điều này là sử dụng giao diện Applicative cho Parsec, thường được coi là kiểu tốt. Các cách nào khác để sử dụng Parsec là giao diện Monad:

email = do 
    a <- many1 alphaNum 
    b <- char '@' 
    c <- many1 alphaNum 
    d <- string ".com" 
    return (a ++ [b] ++ C++ d) 
+0

Đây có phải là con đường thành ngữ để hoàn thành nhiệm vụ nói? Tôi sẽ không sử dụng mã sản xuất ở bất cứ đâu. Tôi chỉ đơn giản là cố gắng để tìm hiểu parsec. – Jay

+0

Cả hai cách đều thành ngữ – nponeccop

Các vấn đề liên quan