import Data.List
import Data.Char
import Data.Maybe
phoneBook =
[("betty", "555-2928")
,("bonny", "092-1029")
,("pasty", "493-9202")
]
findKey :: (Eq k) => k -> [(k,v)] -> Maybe v
findKey key [] = Nothing
findKey key ((k,v):xs)
| key == k = Just v
| otherwise = findKey key xs
main :: IO()
main = do
putStrLn "hello"
putStrLn (show fromMaybe (findKey "penny" phoneBook))
putStrLn (show fromMaybe (findKey "bonny" phoneBook))
=============================================== ===============
dictionary.hs:24:22:
Couldn't match type `Maybe [Char]' with `[Char]'
Expected type: String
Actual type: Maybe [Char]
In the return type of a call of `findKey'
In the first argument of `putStrLn', namely
`((findKey "bonny" phoneBook))'
In a stmt of a 'do' block: putStrLn ((findKey "bonny" phoneBook))
当我尝试从putStrLn
打印值时,我fromMaybe
抛出错误的原因是什么?
答案 0 :(得分:8)
show fromMaybe (findKey "penny" phoneBook)
将两个参数传递给show
:第一个是fromMaybe
,第二个是findKey "penny" phoneBook
。你需要括号来传递一个:
show (fromMaybe (findKey "penny" phoneBook))
但还有另一个问题。 fromMaybe
有两个参数,你只给它一个。它的第一个参数应该是一个默认值,如果结果可能是Nothing
。
答案 1 :(得分:7)
首先,您必须了解fromMaybe
的工作原理。引用文档,
fromMaybe
函数采用默认值和Maybe
值。如果Maybe
为Nothing
,则返回默认值;否则,它返回Maybe
中包含的值。
因此,您需要将两个值传递给fromMaybe
,并且第一个值是要使用的默认值,以防Maybe
变成Nothing
。但在你的情况下,你只传递一个论点,
fromMaybe (findKey "penny" phoneBook)
fromMaybe (findKey "bonny" phoneBook)
您只是将实际Maybe
值传递给使用,缺少默认值。所以,把它改成像
fromMaybe "Not Found" (findKey "penny" phoneBook)
fromMaybe "Not Found" (findKey "bonny" phoneBook)
现在我们对fromMaybe
部分很好。但是,如果您的代码是这样的话,它仍然会失败
show fromMaybe "Not Found" (findKey "penny" phoneBook)
show fromMaybe "Not Found" (findKey "bonny" phoneBook)
因为,这意味着,您将三个参数传递给show
,即fromMaybe
,"Not Found"
和(findKey "penny" phoneBook)
。但show
只需要一个值。引用show
documentation,
<强>
show :: a -> String
强>
showsPrec
的专用变体,使用优先级上下文零,并返回普通的String。
它只需要值并返回String
。所以你需要传递fromMaybe
返回的值,就像这个
show (fromMaybe "Not Found" (findKey "penny" phoneBook))
show (fromMaybe "Not Found" (findKey "bonny" phoneBook))
仍然会失败,因为putStrLn
只需要一个参数,按照the documentation,
<强>
putStrLn :: String -> IO ()
强>与
putStr
相同,但添加换行符。
所以,你只需要将show
的结果传递给putStrLn
,就像这样
putStrLn (show (fromMaybe "Not Found" (findKey "penny" phoneBook)))
putStrLn (show (fromMaybe "Not Found" (findKey "bonny" phoneBook)))
现在,它将打印,
hello
"Not Found"
"092-1029"
注1:如果您不喜欢这么多括号,可以使用$
运算符,该运算符执行隐式函数应用程序。引用$
,
<强>
($) :: (a -> b) -> a -> b
强>应用程序运营商。此运算符是多余的,因为普通应用程序
(f x)
与(f $ x)
相同。但是,$
具有低的,右关联的绑定优先级,因此它有时允许省略括号;例如:f $ g $ h x = f (g (h x))
它在高阶情况下也很有用,例如
map ($ 0) xs
或zipWith ($) fs xs
。
所以,你可以简单地删除不必要的parens并编写像这样的代码
putStrLn $ show $ fromMaybe "Not Found" (findKey "penny" phoneBook)
putStrLn $ show $ fromMaybe "Not Found" (findKey "bonny" phoneBook)
注2:在这种特殊情况下,由于您的fromMaybe
已经返回[Char]
,因此您可以跳过show
并传递{fromMaybe
的结果1}}到putStrLn
,像这样
putStrLn $ fromMaybe "Not Found" (findKey "penny" phoneBook)
putStrLn $ fromMaybe "Not Found" (findKey "bonny" phoneBook)