1

我试图弄清楚 Haskell 中的迭代 I/O 是什么。我用一些定义检查了以下 Haskell-Wiki 。

我不明白该函数的第二行、第三行和最后两行的含义:

enumerator :: FilePath -> Iteratee (Maybe Char) o -> IO o
enumerator file it = withFile file ReadMode
  $ \h -> fix (\rc it -> case it of
    Done o -> return o
    Next f -> do
      eof <- hIsEOF h
      case eof of
        False -> do
          c <- hGetChar h
          rc (f (Just c))
        True -> rc (f Nothing)
    ) it

我知道, iteratee 函数做了什么,但我不明白一些行。这个维基页面上的其他功能真的很神秘。我不明白他们在做什么,因为我错过了一些解释。

4

2 回答 2

4

您提到的行不是特定于枚举器/迭代器的,尽管我可以尝试解释它们。


withFile name mode = bracket (openFile name mode) (closeFile)

换句话说,withFile打开一个文件,将句柄传递给给定的回调,并确保在回调完成后关闭文件。


fix是一个定点组合器。例如,

fix (1 :) == 1 : 1 : 1 : 1 : ...

它通常用于编写自递归函数。TFAE:

factorial 0 = 1
factorial n = n * factorial (n-1)

factorial n = fix (\f n -> case n of 0 -> 1; n -> n * f (n-1)) n

我们可以在没有这些结构的情况下重写相同的函数:

enumerator :: FilePath -> Iteratee (Maybe Char) o -> IO o
enumerator file it = do
  h <- openFile file ReadMode
  let rc (Done o) = return o
      rc (Next f) = do
        eof <- hIsEof h
        case eof of
          False -> do
            c <- hGetChar h
            rc (f (Just c))
          True -> rc (f Nothing)
  o <- rc it
  closeFile h
  return o

尽管它在withFile处理异常时并不完全准确,但事实并非如此。

这有帮助吗?

于 2012-07-13T01:07:14.627 回答
2

如果命名 lambda 函数可能会有所帮助。

enumerator :: FilePath -> Iteratee (Maybe Char) o -> IO o
enumerator file it = withFile file ReadMode $ stepIteratee it
  where
    stepIteratee (Done o) _h = return o
    stepIteratee (Next f) h = do
      eof <- hIsEOF h
      case eof of
        False -> do
          c <- hGetChar h
          stepIteratee (f (Just c)) h
        True -> stepIteratee (f Nothing) h

stepIteratee将继续遍历文件和迭代对象,直到迭代对象停止。

于 2012-07-13T06:56:21.123 回答