2012-12-31 83 views
1

我想寫一個非常簡單的編輯器,如「ed」。 在這個程序中,我試圖使用一個映射來構建控件,該控件在要執行的動作中轉換字符串命令。 這裏有一段代碼:在haskell中使用Data.Map的奇怪的錯誤

commands :: Map String ([Handle] -> IO()) 
commands = fromAscList [ 
    ("o",\list -> print "Insert name of the file to be opened" >> getLine >>= \nomefile -> 
     openFile nomefile ReadWriteMode >>= \handle -> editor (handle:list)), 
    ("i",\list -> case list of { [] -> print "No buffer open" ; handle:res -> write handle } >> editor list), 
    ("q",\list -> if list == [] then return() else mapM_ hClose list >> return()) 
] 

editor :: [Handle] -> IO() 
editor list = do 
    command <- getLine 
    let action = lookup command commands 
    case action of 
    Nothing -> print "Unknown command" >> editor list 
    Just act -> act list 

的問題是,當我執行的編輯功能,無論是在ghci中或可執行文件,當我輸入「O」我得到的消息「未知的命令」,而不是調用函數打開文件。我已經使用關聯列表而不是Map來嘗試相同的代碼,在這種情況下它可以工作。那麼這裏可能是什麼問題?

更奇怪的是,如果我在ghci中的映射命令上調用鍵,它將返回一個包含字符串「o」的列表。

我事先感謝您的幫助。

+1

您是否導入了前導隱藏(查找)'?無論如何,如果你沒有,你會得到一個錯誤。我還沒有看到問題......如果你在案例之前「打印命令」以確保沒有有趣的I/O事件發生,該怎麼辦? – luqui

+0

「getLine」不包含尾隨的換行符嗎? – 2012-12-31 19:20:27

+0

@Tinctorius,nope – luqui

回答

6
commands :: Map String ([Handle] -> IO()) 
commands = fromAscList [ 
    ("o",_), 
    ("i",_), 
    ("q",_) 
] 

ghci> Data.List.sort ["o","i","q"] 
["i","o","q"] 

你在騙Data.Map,所以它構建了Map未滿足所需不變。因此,查找Map中的內容不起作用,因爲請求已發送到錯誤的分支(有時)。

+0

所以,這只是一個順序問題,非常感謝,順便說一下,爲什麼算法需要列表排序呢? –

+4

'fromAscList'需要對列表進行排序。如果你已經使用'fromList',它會起作用。如果鍵被排序,'Map'可以更高效地構建,這就是爲什麼'fromAscList'和'fromDistinctAscList'存在的原因。 –

+0

很酷,再次感謝:D –