File 保存haskell之前按长度筛选文件

File 保存haskell之前按长度筛选文件,file,haskell,filter,File,Haskell,Filter,有人问了一个类似的问题,但手头有一份清单: 我已经知道如何从文件中获取单词列表 getWords path = do contents <- readFile path return (lines contents) getWords path=do contents我不确定我是否完全理解这个问题。它围绕着“在将其保存为单词列表之前”的概念展开,这在一种懒惰的语言中似乎具有误导性。在哈斯克尔,你在做什么 let list1 = someLongLi

有人问了一个类似的问题,但手头有一份清单:

我已经知道如何从文件中获取单词列表

getWords path = do contents <- readFile path
                   return (lines contents)

getWords path=do contents我不确定我是否完全理解这个问题。它围绕着“在将其保存为单词列表之前”的概念展开,这在一种懒惰的语言中似乎具有误导性。在哈斯克尔,你在做什么

let list1 = someLongList
    list2 = filter p list1 
in use list2              -- (but do not use list1)
不会导致
list1
完全存储在内存中:相反,不满足
p
的元素将立即被丢弃。 因此,在“保存”列表之前过滤列表的概念没有意义:这是编译器将为您执行的标准优化


相反,分离输入/输出和过滤是首选方法。另一种方法,即在代码中混合I/O和纯计算,通常被认为是更糟糕的方法。Haskell类型也鼓励第一种更简单的方法。

我不确定我是否完全理解这个问题。它围绕着“在将其保存为单词列表之前”的概念展开,这在一种懒惰的语言中似乎具有误导性。在哈斯克尔,你在做什么

let list1 = someLongList
    list2 = filter p list1 
in use list2              -- (but do not use list1)
不会导致
list1
完全存储在内存中:相反,不满足
p
的元素将立即被丢弃。 因此,在“保存”列表之前过滤列表的概念没有意义:这是编译器将为您执行的标准优化


相反,分离输入/输出和过滤是首选方法。另一种方法,即在代码中混合I/O和纯计算,通常被认为是更糟糕的方法。Haskell类型也鼓励第一种更简单的方法。

使用
IO
也是
函子的一个实例这一事实

filteredWords <- fmap (filter (\x -> length x == 3)) $ getWords path

我认为
readFile
Prelude
中,如果不是,那么它将在
系统中。IO

使用
IO
也是
Functor
的一个实例这一事实

filteredWords <- fmap (filter (\x -> length x == 3)) $ getWords path

我认为
readFile
Prelude
中,如果不是,那么它将在
System.IO中。下面是一个使用
pipes
的示例,它可以避免实现完整的单词列表。只有指定长度的字将保留在内存中:

import Pipes
import qualified Pipes.Prelude as Pipes
import qualified System.IO as IO

filteredWords :: FilePath -> IO [String]
filteredWords path =
    IO.withFile path IO.ReadMode (\handle -> Pipes.toListM (
        Pipes.fromHandle handle >-> Pipes.filter (\x -> length x == 3) ))

例如,如果您的文件有1000000个单词,但其中只有4个单词的长度为3,那么这个程序将只生成长度为4的列表。所有其他元素在读取后会立即被丢弃,不会存储在某个中间列表的内存中。

是。下面是一个使用
pipes
的示例,它可以避免实现完整的单词列表。只有指定长度的字将保留在内存中:

import Pipes
import qualified Pipes.Prelude as Pipes
import qualified System.IO as IO

filteredWords :: FilePath -> IO [String]
filteredWords path =
    IO.withFile path IO.ReadMode (\handle -> Pipes.toListM (
        Pipes.fromHandle handle >-> Pipes.filter (\x -> length x == 3) ))

例如,如果您的文件有1000000个单词,但其中只有4个单词的长度为3,那么这个程序将只生成长度为4的列表。所有其他元素在读取后会立即被丢弃,不会存储在内存中的某个中间列表中。

在“filteredWords Before”之前,filteredWords这一个短而甜美,与我已有的getWords完美结合。如果不使用getWords(仍然是一行),我会等待更多的答案,如果没有,我会接受这个答案。这个答案简短而甜美,与我已有的getWords完美结合。如果不使用getWords(仍然是一行),我会等待更多的答案,如果没有,我会接受这个答案。FWIW,
(行内容)
是行列表,而不是单词。FWIW,
(行内容)
是行列表,而不是单词。