2017-02-26 61 views
0

我是新来的Haskell和下面的代码是给我两个错误:无法与地图匹配型IO,不能用[字符]匹配类型地图

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]。我不明白这一点,因为该函数应该返回一个地图,但它要求[Char]

任何帮助,将不胜感激:d

回答

5

你混合纯与不纯的代码 - 这可能会制定出在不太严格的编程语言,但哈斯克尔让你“标签”的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项填补了一个电话簿和这个返回给你 - 这是什么你想要它做什么? - 我不知道!

+0

谢谢,我刚刚进入Haskell,我认为做几件简单的事情会帮助我学习,显然它工作... – SchoolBoy

相关问题