在Haskell中解析Graph Dimacs格式的直觉 [英] Intuition in parsing Graph Dimacs format in Haskell

查看:289
本文介绍了在Haskell中解析Graph Dimacs格式的直觉的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Haskell的初学者,我正在尝试学习一些小册子,所以我会倾听你的帮助。我读了几本书和指南,但我无法理解如何使用IO操作。我正在尝试用格式解析文件并创建图形对象。到目前为止,我有这样的代码:(节点由正整数标识)

I'm a beginner in Haskell, and I'm trying to learn few concenpts so I would appretiate your help. I read few books and guides but I can't understand how can I use IO operations. I'm trying to parse file in this format and create graph object. So far I have this code: (nodes are identified by positive integer)

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是懒惰的。我想用签名创建函数

I understand that haskell is lazy. I want to create function with signature

parseInput :: String -> Maybe Graph

所以我得到 Nothing on错误或图表。我的问题是我不能简单地读取文件并在一个函数中创建图形。据我所知,我应该得到IO String,创建对象,然后使用句柄关闭文件?有人能指出我正确的方向吗?我对此很难,因为它与命令式语言非常不同。

so I either get Nothing on error or Graph. My problem is that I can't simply read the file and create the graph in one function. As far as I understand, I'm supposed to get IO String, create the object and then close the file using handle? Could anyone point me in the right direction? I'm having a hard time with this because it's very different from imperative languages.

感谢您的任何建议。

推荐答案

你可以把它想象成两个不同的世界:

You can think of it as two different worlds:


  • 确定性的,普通世界所有纯函数在哪里,

  • 神奇IO世界其中文件活着,你真的不知道会发生什么。

  • the deterministic, ordinary world where all pure functions live, and
  • the magical IO world where files live, and where you don't really know what could happen.

当有人说 IO 是一个monad,你可以理解它:你可以做任何神奇的IO事情,但是一旦施法,就没有办法回到普通状态。

When someone says IO is a monad, you can understand it thus: you can make anything a magical IO thing, but once the spell is cast, there's no way back to the ordinary.

因此, IO 类型的函数是你的法术,而 parseInput 是一个普通的,完全可预测的机械device:对于任何给定的输入,您可能始终知道输出将是什么。一旦你掌握了技巧,你必须召唤一些内容 readFile ,然后使用 fmap 将普通函数移动到神奇的IO世界:

So, functions of type IO are your spells, and the parseInput is an ordinary, totally predictable mechanical device: for any given input, you may always know what the output will be. Once you have your mechanics in place, you have to conjure some contents with readFile, and then move your ordinary function to the magical IO world as well with fmap:

parseInput :: String -> Maybe Graph
parseInput = ...

magicallyGetContents :: IO String
magicallyGetContents = readFile ...

parseMagicalInput :: IO String -> IO (Maybe Graph)
parseMagicalInput = fmap parseInput

到此为止,您可以申请解析器:

By this point, you can apply your parser:

λ :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)

有几个法术可以随意使用可以帮助你穿越神奇的一面。最简单的是:

There are several spells at your disposal that can help you cross to the magical side. The simplest would be:

return :: a -> IO a

(这个名字暗示着神奇的世界实际上是Haskell所有事物的家园。)

请注意,一旦你应用了这个相当简单的法术,就无法回头了。虽然理论上你可以通过RAM破解并检索字节,但这并不简单。例如,这不会:

Notice that once you apply this fairly simple spell, there is no way back. Though you theoretically could hack your way through the RAM and retrieve the bytes, it will not be straightforward. For example, this won't do:

λ print $ (unsafeCoerce (return 2 :: IO Int) :: Int)
1099511628032






所以,你的方式是假设你拥有纯净世界中的内容,并构建你的机器然后工作,然后穿过它的interworld障碍,并将其应用到另一侧的任意数量的DIMACS图形文件。


So, your way is to assume you have the contents in the pure world, and build your machine that would then work, then cross the interworld barrier with it and apply it to any number of DIMACS graph files there on the other side.

快乐的冒险!

ps 你也可以检查这个答案是为了更加脚踏实地的观点。

p.s. You may also check this answer for a more down-to-earth point of view.

这篇关于在Haskell中解析Graph Dimacs格式的直觉的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆