2014-10-02 66 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