我在读取Haskell中的级别文件时遇到了问题。目标是读入一个简单的txt文件,其中两个数字由空格分隔,然后是逗号。我一直得到的问题是:无法匹配类型`IO' with `[]'
如果我理解正确的话,do语句应该是从Monad中拉出字符串。
readLevelFile :: FilePath -> [FallingRegion]
readLevelFile f = do
fileContent <- readFile f
(map lineToFallingRegion (lines fileContent))
lineToFallingRegion :: String -> FallingRegion
lineToFallingRegion s = map textShapeToFallingShape (splitOn' (==',') s)
textShapeToFallingShape :: String -> FallingShape
textShapeToFallingShape s = FallingShape (read $ head numbers) (read $ head
$ tail numbers)
where numbers = splitOn' (==' ') s发布于 2017-10-16 02:11:16
你不能把东西从IO中拉出来。您可以将IO想象成一个容器(实际上,对IO的一些解释将其比作装有Schrödinger的猫的盒子)。您看不到容器中有什么,但是如果您步入容器,值就会变得可见。
因此,这应该是可行的:
readLevelFile f = do
fileContent <- readFile f
return (map lineToFallingRegion (lines fileContent))但是,它不具有操作中给出的类型。在do块中,fileContent是一个String值,但整个块仍然在IO容器中。
这意味着函数的返回类型不是[FallingRegion],而是IO [FallingRegion]。因此,如果您将readLevelFile的类型注释更改为
readLevelFile :: FilePath -> IO [FallingRegion]你应该能够跨过第一个障碍。
发布于 2017-10-16 02:11:00
让我们来看看你的第一个显式类型的函数:
readLevelFile f = do
(fileContent :: String) <-
(readFile :: String -> IO String) (f :: String) :: IO StringfileContent确实是String类型,但仅在我们正在评估的IO Monad的执行中可用。这次又是什么?
(map lineToFallingRegion (lines fileContent)) :: [String]现在,您突然使用了一个表达式,它不是IO monad,而是一个列表值--因为列表也是monad的一种类型,所以类型检查试图将IO与[]统一起来。你真正想要的是返回这个值:
return (map lineToFallingRegion (lines fileContent)) :: IO [String]现在回想一下,我们永远不能“退出”IO monad你的readLevelFile类型必须是IO -诚实地承认它与外部世界交互:
readLevelFile :: FilePath -> IO [FallingRegion]https://stackoverflow.com/questions/46757938
复制相似问题