我是Haskell的新手,下面的代码给了我两个错误:
import Control.Monad
import Control.Applicative
import System.IO
import qualified Data.Map as Map
import Data.Maybe
main = do
return ()
getPhonebook :: Int -> (Map.Map String String)
getPhonebook n
| n == 0 = Map.empty
| otherwise = do
line <- getLine
let split = words line
return (Map.insert (split !! 0) (split !! 1) (getPhonebook (n-1)))
第一个错误出现在line <- getLine
行上。错误说Couldn't match type ‘IO’ with ‘Map.Map String’
。我不明白这个错误,可能是一个愚蠢的错误。
第二个错误发生在返回行。它显示Couldn't match type ‘Map.Map String String’ with ‘[Char]’
,预期类型为[Char]
。我不明白这个,因为该函数应该返回一个Map,但它要求[Char]
。
任何帮助将不胜感激:D
答案 0 :(得分:5)
你正在混合纯粹的不纯的代码 - 这可能在不太严格的编程语言中有效但是haskell让你“标记”IO
的每一次使用 - 通过把你放在IO monad中(有不安全的方法) - 所以,让我们不要关注那些)。
你向GHC承诺 - getPhonebook :: Int -> (Map.Map String String)
这意味着对于getPhonebook域中的每个Int
,您将返回(Map String String)
- pureley而无需任何用户输入。
现在在函数体中,您不能使用getLine
等来实现此承诺。
因此,让我们更改类型并确认使用IO。
getPhonebook :: Int -> IO (Map.Map String String)
现在您的基本情况与IO操作不匹配,但可以使用return ...
轻松修复此问题。
但是GHC仍然存在一个问题 - Map.insert
是纯粹的,并且不会接受getPhonebook (n-1)
,因为这是一个IO动作。如何解决此问题 - 将此操作绑定到名称previousPB <- getPhonebook (n-1)
。
将这些放在一起我们得到以下代码:
getPhonebook :: Int -> IO (Map.Map String String)
getPhonebook n
| n == 0 = return Map.empty
| otherwise = do
line <- getLine
let split = words line
previousPB <- getPhonebook (n-1)
return $ Map.insert (split !! 0) (split !! 1) previousPB
现在问题是这样做了什么 - 它通过向你询问n
条目来填写电话簿并将其归还给你 - 这是你想要的吗? - 我不知道!