我怎么打印一个Maybe?

时间:2015-03-08 05:25:36

标签: haskell maybe

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抛出错误的原因是什么?

2 个答案:

答案 0 :(得分:8)

show fromMaybe (findKey "penny" phoneBook)

将两个参数传递给show:第一个是fromMaybe,第二个是findKey "penny" phoneBook。你需要括号来传递一个:

show (fromMaybe (findKey "penny" phoneBook))

但还有另一个问题。 fromMaybe有两个参数,你只给它一个。它的第一个参数应该是一个默认值,如果结果可能是Nothing

答案 1 :(得分:7)

首先,您必须了解fromMaybe的工作原理。引用文档,

  

fromMaybe函数采用默认值和Maybe。如果MaybeNothing,则返回默认值;否则,它返回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) xszipWith ($) 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)