Haskell 从文件中读取 Map

3

我已经将一个地图写入文件,现在想对其执行读取操作。这是否可行?其中一个问题是代码使用ByteString和ByteString.Char8进行编写和读取。我一直收到以下错误:

fromList *** Exception: Prelude.read: no parse

我的代码如下:

import qualified Data.ByteString.Char8 as BSC
import qualified Data.ByteString as BS
import qualified Data.Map as Map

type Code = Map.Map Char [Bit]

writeCode :: FilePath -> Code -> IO ()
writeCode fp tr = BS.writeFile ("code_" ++ fp)
                  (BSC.pack (show (tr :: M.Map Char [Bit])))

readCode :: FilePath -> IO Code
readCode f = do s <- BS.readFile ("code_" ++ f)
                let s' = BSC.unpack s
                return (read s' :: Code)

你能否给出一个示例 Code,将其写入文件中,以便可以重现错误? - Willem Van Onsem
fromList [('e',[1,1,0]),('h',[1,1,1]),('l',[0]),('o',[1,0])]是一个示例。当我将其写入文件时,它就会以这种方式出现在文件中,但现在我无法读取它。抱歉,Bit是一种具有One或Zero的数据类型,用1或0表示。 - astiefel
tr2 = read $ show $ tr :: Code 有相同的效果吗?您能否提供完整的代码以重现此问题? - Luka Rahne
@LukaRahne:这应该是相同的,因为“Code”是“Map.Map”的别名... - Willem Van Onsem
2
提醒一下,data Bit = One | Zero deriving (... , Ord) 这个定义非常奇怪,因为它会得出 One < Zero 的结论!你几乎肯定想要重新排列这些构造函数。 - dfeuer
显示剩余5条评论
1个回答

5
问题在于您覆盖了Show的默认实现,但仍依赖于Read的默认实现,该实现期望“One”或“Zero”,而不是“1”或“0”。
解决方案是编写自己的Read实现(可以将Eq和Ord保留为原样):
import qualified Data.ByteString.Char8 as BSC
import qualified Data.ByteString as BS
import qualified Data.Map as Map

data Bit = One | Zero deriving (Eq,Ord)

instance Show Bit where
  show One = "1"
  show Zero = "0"

instance Read Bit where
  readsPrec _ ('1':xs) = [(One, xs)]
  readsPrec _ ('0':xs) = [(Zero, xs)]
  readsPrec _ _        = []

type Code = Map.Map Char [Bit]

writeCode :: FilePath -> Code -> IO ()
writeCode fp tr = BS.writeFile ("code_" ++ fp) (BSC.pack (show tr))

readCode :: FilePath -> IO Code
readCode f = do s <- BS.readFile ("code_" ++ f)
                let s' = BSC.unpack s
                return (read s' :: Code)

非常感谢。我以前从未重写过read函数,所以它给了我一个关于以下模式不匹配的警告:_ ((GHC.Types.C# #x) : _) with #x notElem ['1', '0']。有没有办法告诉它只使用正常的read函数? - astiefel
1
在Read实例中缺少一个情况,我已经更新了我的答案。 - Michael Szvetits

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接