2

我正在从 Java 到 Haskell 朝圣。从广义上讲,我了解了 Haskell 背后的主要概念。阅读所有的教程和书籍“很有意义”,但我被困在从头开始编写自己的代码。

我想在文件系统上创建 1000 个文件名

“myfile_1.txt” ... “myfile_1000.txt”

每个都包含一些虚拟文本。

到目前为止,我已经解决了整个 IO 问题,并意识到我需要构建一个包含 1000 个元素的字符串列表。所以我有:

buildNamesList :: [] -> []
buildNamesList ???

一旦我有了 List,我就可以在每个元素上调用 writefile 方法。我不知道如何在字符串的末尾添加一个数字来获取每个文件名,因为我不能在 Haskell 中有一个 int i = 0, i ++ 构造。

我在这里有点超出我的深度,希望得到一些指导,谢谢

4

4 回答 4

7

一种可能的解决方案:

buildNamesList = map buildName [1..1000]
  where buildName n = "myfile_" ++ show n ++ ".txt"
于 2013-07-08T11:15:05.473 回答
5
import Control.Applicative

fileNames = ("myFile_"++) <$> (++".txt")  <$> show <$> [1..1000]
于 2013-07-08T11:51:10.910 回答
2

然后我如何遍历它,在元素 n 处提取字符串,然后将其传递给另一个函数?

不!从低效的列表中“挑选”一些东西。您不想担心如何获取每个元素,然后对其进行处理。这在命令式语言中是必要的,因为它们对“排序操作”的含义没有适当的抽象——这只是语言中内置的一些神奇的东西。Haskell 对此有更明确的、数学上合理的和类型安全的魔法;因此,您不需要循环等。

您知道如何处理每个元素 ( String -> IO ()),并且您知道数据的来源 ( [String])。你也知道最终会发生什么(IO ())。因此,您要查找的组合器具有 type ( String -> IO() ) -> [String] -> IO (),但显然它并不真正依赖于 String 的数据,所以让我们将其简化为(a -> IO()) -> [a] -> IO(). 您可以在 Hoogle 上查找,它提供了 sume rubbishmapM_forM_,两者都可以满足您的需求:

mapM_ (\filename -> writeFile filename "bla") filenamesList

或者

forM_ filenamesList $ \filename ->
   writeFile filename "bla"
于 2013-07-08T12:39:32.950 回答
0

有时我认为它与循环foldr有些相似。for这是一种类似于i++构造的东西,i在循环中应用:

foldr (\i accum -> ("myfile_" ++ show i ++ ".txt") : accum) [] [1..1000]


另一种方法可能是zipWith,它应用一个函数来组合两个列表:

zipWith (\a b -> a ++ show b ++ ".txt") (repeat "myfile_") [1..1000] 

或者

zipWith ($) (repeat (("myfile_" ++) . (++ ".txt") . show)) [1..1000]


这也是一个递归示例,应用为fileList "myfile_" ".txt" [1..1000]

fileList _     _   []     = [] 
fileList fName ext (x:xs) = (fName ++ show x ++ ext) : fileList fName ext xs
于 2013-07-08T18:12:12.160 回答