我是Haskell的初学者,我正在努力学习几个小册子,所以我会倾听你的帮助。我读了几本书和指南,但我无法理解如何使用IO操作。我正在尝试以this格式解析文件并创建图形对象。到目前为止,我有这个代码:(节点由正整数标识)
data Edge = Edge Int Int deriving(Show)
data Graph = Graph {
nodeCount :: Int,
edges :: [Edge]
} deriving (Show)
parseInput :: String -> IO ()
parseInput filePath = do
handle <- openFile filePath ReadMode
contents <- hGetContents handle
putStrLn contents
hClose handle
我明白haskell是懒惰的。我想创建带签名的功能
parseInput :: String -> Maybe Graph
所以我在错误或图表上得到Nothing
。我的问题是我不能简单地读取文件并在一个函数中创建图形。据我所知,我应该得到IO String,创建对象,然后使用句柄关闭文件?有人能指出我正确的方向吗?我对此很难,因为它与命令式语言非常不同。
感谢您的任何建议。
答案 0 :(得分:1)
您可以将其视为两个不同的世界:
当有人说IO
是一个monad时,你可以理解它:你可以做任何神奇的IO事情,但是一旦施放了法术,就没有办法回到平凡状态。
因此,IO
类型的函数是你的法术,而parseInput
是一个普通的,完全可预测的机械装置:对于任何给定的输入,你可能总是知道输出是什么。一旦你掌握了技巧,你必须召唤一些contents
和readFile
,然后将你的普通函数移动到神奇的IO世界以及{{1} }:
fmap
到目前为止,您可以应用解析器:
parseInput :: String -> Maybe Graph
parseInput = ...
magicallyGetContents :: IO String
magicallyGetContents = readFile ...
parseMagicalInput :: IO String -> IO (Maybe Graph)
parseMagicalInput = fmap parseInput
你可以使用几种法术来帮助你进入神奇的一面。最简单的是:
λ :t parseInput magicallyGetContents
-- This won't work because of the interworld barrier.
<interactive>... error:
• Couldn't match type ...
Expected type: String
Actual type: IO String
...
λ :t parseMagicalInput magicallyGetContents
-- This is fine, because both things are on the magical side.
parseMagicalInput magicallyGetContents :: IO (Maybe Graph)
(这个名字暗示着神奇的世界实际上是哈斯克尔所有事物的家园。)
请注意,一旦你应用了这个相当简单的法术,就无法回头了。虽然理论上你可以通过RAM破解并检索字节,但这并不简单。例如,这不会:
return :: a -> IO a
所以,你的方法是假设你拥有纯净世界中的内容,并构建你的机器然后工作,然后穿过它的interworld障碍并将其应用于任何数量的DIMACS另一边有图形文件。
快乐的冒险!
p.s。您还可以查看this answer以获得更实际的观点。