2014-10-02 63 views
2

嘗試在this頁面上擴展「Maybe monad」示例。他們查找表phonebookHaskell查找表返回函數

phonebook :: [(String, String)] 
phonebook = [ ("Bob", "01788 665242"), 
       ("Fred", "01624 556442"), 
       ("Alice", "01889 985333"), 
       ("Jane", "01732 187565") ] 

,有鏈單子例子:

getRegistrationNumber :: String  -- their name 
         -> Maybe String -- their registration number 
getRegistrationNumber name = 
    lookup name phonebook >>= 
    (\number -> lookup number governmentalDatabase) 

如果我們想返回的功能會發生什麼(即然後返回一個特定類型的)呢?因此,從他們的例子延伸出來,而不是查找註冊號碼,我們希望查找他們的年齡,他們的郵政編碼,或財產稅支付的年份。鑑於這些例子,INT似乎適用於前兩個,最後一個List of Ints第一個問題:由於查找表有一個類型,函數的所有返回類型是否必須是相同類型?我假設是,但我不確定,因此下一個問題。

可以說我們寫這些'找到'函數返回相同的類型[Int]。也許像這些:

getAge :: String -> Maybe [Int] 
getAge phoneNumberString = 
    lookup name phonebook >>== 
     (\phoneNumberString -> lookup phoneNumberString governmentalAgeDatabase) 
getZip :: String -> Maybe [Int] 
getZip phoneNumberString = 
    lookup name phonebook >>== 
     (\phoneNumberString -> lookup phoneNumberString governmentalZipCodeDatabase) 
getTaxPaidYears :: String -> Maybe [Int] 
getTaxPaidYears phoneNumberString = 
    lookup name phonebook >>== 
     (\phoneNumberString -> lookup phoneNumberString governmentalTaxYearDatabase) 

現在,假設每個的*Database S的返回[Int]類型,第二個問題我們如何寫一個功能類似lookupPersonsInformation,將返回從什麼在輸入中鍵入相應的信息字符串,並給出一個返回適當的函數的查找,返回請求的信息?以下是我努力使工作:

lookupAppropriateFunction :: [(String, String -> [Int])] --Here I want the second part 
                -- of the tuple to be the functions 
lookupAppropriateFunction = [ ("age", getAge), 
           ("zip", getZip), 
           ("taxes", getTaxPaidYears) ] 

lookupPersonsInformation :: String -> Maybe [Int] 
lookupPersonsInformation nameAndInfo = 
    lookup (words nameAndInfo!!0) >>= 
    (\phoneNumberString -> lookup (words nameAndInfo!!1) lookupAppropriateFunction) 

-- >> lookupPersonsInformation "Bob age" 
     [53] --Bob's age 
-- >> lookupPersonsInformation "Fred zip" 
     [28202] --Fred's age 
-- >> lookupPersonsInformation "Alice taxes" 
     [2010,2011,2013] --Alice's paid taxes years, It looks like she skipped 2012 :) 

很明顯的錯誤進行到底的Nothing傳播,但我不知道該如何採取將其應用到一個高階函數的下一個步驟。它是更多的使用words解析或查找表的結構,我想回到一個function`

+3

每個人都有一個年齡,一個郵政編碼和稅務信息(據推測)。因此,'lookupPersonInfo'應該有'String - > Maybe PersonInfo'類型,其中'data PersonInfo = PersonInfo {personName :: String,personAge :: Int,personTaxYears :: [Int]}'。然後你有'fmap personAge(lookupPersonInfo「bob」)''''fmap personName(lookupPersonInfo「bob」)'等等 – user2407038 2014-10-02 03:26:46

回答

0

我結束了與類似下面的打算:

------------------------------------------------------------------------- 
intPusher :: String -> Stack -> Maybe Stack 
--^Takes a word, and tries to turn it into an Int, and push it onto the stack 
intPusher word = case (reads word) of 
    []  -> \stak -> Nothing 
    [(x,"")] -> \stak -> Just (x:stak) 
    [(x,y)] -> \stak -> Nothing 
------------------------------------------------------------------------- 
dicLookup :: String -> Stack -> Maybe Stack 
--^Takes a word, and looks it up in the dictionary 
dicLookup word = case (lookup word wordsTable) of 
    Nothing -> intPusher word 
    Just f -> f 
------------------------------------------------------------------------- 
wordsTable :: [(String, Stack -> Maybe Stack)] 
--^Checks the string against the commands 
wordsTable = [ ("+", addIt) 
       ,("-", subIt) 
       ,("*", multIt) 
       ,("/", divIt) 
       ,("/MOD", modQuotIt) 
       ,("MOD", modIt) 
       .... 
       ,("2DROP", drop2It) ] 
------------------------------------------------------------------------- 
interpretProgram :: String -> Maybe Stack 

interpretProgram str = foldl (>>=) (Just[]) (map dicLookup (words str)) 

併爲每個元組字典中的值,我提供的函數聲明:

------------------------------------------------------------------------- 
addIt :: Stack -> Maybe Stack 
--^Adds the first two elements of the stack 
addIt stak = case stak of 
    x:y:xs -> Just (x + y:xs) 
    x:xs -> Nothing 
    _  -> Nothing 
------------------------------------------------------------------------- 
subIt :: Stack -> Maybe Stack 
--^Subtracts the first two elements of the stack 
subIt stak = case stak of 
    x:y:xs -> Just (y - x:xs) 
    x:xs -> Nothing 
    _  -> Nothing 
------------------------------------------------------------------------- 
multIt :: Stack -> Maybe Stack 
--^Multiplies the first two elements of the stack 
multIt stak = case stak of 
    x:y:xs -> Just (x * y:xs) 
    x:xs -> Nothing 
    _  -> Nothing 

... 

此功能會採取一個字符串,分解成各個「單詞」(如果可能的話,返回Nothing如果它不能)被然後進入一本字典來廁所將單詞的值與字典中的鍵相比較,從而起到查找表的作用。如果單詞是字典中的一個鍵,它將返回值,該值是執行某些任務的高階函數(就像單詞函數一樣,如果高階函數遇到錯誤,它將返回Nothing)。

在處理Monads時,只有兩種類型的返回值。 Maybe AnyTypeNothingAnyType可以是已經在模塊中聲明的任何類型,或Haskell中的任何基本類型(Int,Char,[Char]等)。訣竅是返回Maybe AnyTypeNothing類型。由於Haskell需要if語句的終端聲明,因此可以約定'捕捉'任何可能的錯誤並將'Nothing'類型傳遞給[grand]父函數的最終返回。

+0

請解釋這是如何回答你問的問題。 – 2014-11-04 08:06:53

+0

@SvenKoschnicke查看最新答案 – 2014-11-04 15:00:13