2017-02-26 82 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

相關問題