2017-05-30 81 views
2

我正在嘗試爲數據Person編寫解析器(data Person)。但是,我必須用<$><*>將它寫在一行中,我嘗試了很多,但是我真的變得「過度」了。爲haskell中的人編寫解析器

解析器類型和往常一樣:

newtype Parser a = Parser (String -> [(a,String)])

而且我有這樣的功能:

parse :: Parser a -> String -> Maybe a

返回的第一個完整的解析。

例如

,如果我有這個簡單的功能:

upper :: Parser Char 
upper = satisfy isUpper 

如果我跑parse upper "A"我得到Just 'A'

我也有這樣一個有趣的功能:

name :: Parser String 
name = (:) <$> (satisfy isUpper) <*> (many $ satisfy isAlpha) 

,正如你可以看到,接受所有字面字符的字符串,並以大寫字母開頭。

這樣:

*Main> parse name1 "hello" 
Nothing 
*Main> parse name1 "Hello" 
Just "Hello" 

到現在爲止一切正常,唯一的問題是,我要爲類(數據類型?!)的人(data Person

所以做這樣的事情,我有這樣的:

data Person = Person String deriving (Eq, Show)

,然後在只有一條線路,我必須寫解析器Person ,但名稱應該滿足功能name,這意味着,名稱應該只是一串文字字符,其中第一個是大寫字母。

,它應該工作這麼:

> parse parserPerson "Chuck" 
Just (Person "Chuck") 
> parse parserPerson "chuck" 
Nothing 

其中:

parserPerson :: Parser Person 
parserPerson = ??? 

正如你所看到的,bevor 「查克」 有Person,所以我要以某種方式使用*>得到它。

而就是這樣,只是與<$>,<*>*>這樣的行。

我沒有線索,而我越來越瘋狂。也許任何人都可以幫助我。

編輯

satisfy :: (Char -> Bool) -> Parser Char -- parse a desired character 
satisfy p = Parser check 
    where 
    check (c:s) | p c = [(c,s)] -- successful 
    check _ = [  ] -- no parse 

many(爲some)從Control.ApplicativeControl.Applicative

+0

什麼是「滿足」和「多」? – syntagma

+0

噢,當然,對不起。我現在寫。 –

+1

假設你的解析器有一個仿函數實例,你應該可以這樣做'parsePerson = Person <$> name' – tsorn

回答

1

正如tsorn說,答案是很容易的功能...

parserPerson :: Parser Person 
parserPerson = Person <$> name1 

和它的作用是因爲Functor Instacnce被定義。

instance Functor Parser where 
    fmap f (Parser p) = Parser $ \s -> map (\(a,b) -> (f a, b)) $ p s 
+1

這裏的關鍵是認識到'Person'既是一個類型也是一個數據構造函數,後者只是一個接受字符串參數並返回'Person'類型值的函數。可以這樣定義數據類型:「data Person = MkPerson String」,在這種情況下,'MkPerson'是一個函數,它接受一個字符串參數並返回一個類型爲'Person'的值。 – tsorn

+0

謝謝兄弟!例如,如果Person是'''Person String Int''我該如何處理字符串和int?我的意思是,我可以爲Numbers創建另一個解析器,但它的工作原理是什麼?所以? :''人<$>名字<*> numberParser'''?我只想在haskell中稍微「深入」一些,並且遇到了一些問題:D –

+0

是的,這是正確的做法。它依賴於應用實例。 – tsorn