试图扩展" The Maybe monad" this页面上的示例。他们的查询表phonebook
:
phonebook :: [(String, String)]
phonebook = [ ("Bob", "01788 665242"),
("Fred", "01624 556442"),
("Alice", "01889 985333"),
("Jane", "01732 187565") ]
并且链接了monad例子:
getRegistrationNumber :: String -- their name
-> Maybe String -- their registration number
getRegistrationNumber name =
lookup name phonebook >>=
(\number -> lookup number governmentalDatabase)
如果我们想要返回一个函数(然后返回一个特定类型)会发生什么?因此,从他们的示例扩展而不是查找注册号,我们希望查找查询年龄,他们的ZIP或支付财产税的年份。鉴于这些示例,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
都返回[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
进行解析还是在查找表的结构中更多,我想返回一个函数`
答案 0 :(得分: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
,如果它可以,然后传递到字典中以查找与字典中的键相比的单词的值,从而起到查找表的作用。如果单词是字典中的键,则返回值,该值是执行某些任务的高阶函数(就像单词function一样,如果高阶函数遇到错误,它将返回Nothing
)
在处理Monads时,只有两种类型的返回值。 Maybe AnyType
和Nothing
。 AnyType
可以是模块中已声明的任何类型,也可以是Haskell中的任何基本类型(Int,Char,[Char]等...)。诀窍是返回Maybe AnyType
或Nothing
类型。由于Haskell需要对if语句进行终端声明,因此可以采用常规方法来捕获'任何潜在的错误,并传递“无所事事”。输入[grand]父函数的最终返回值。