不能将类型[]与IO

时间:2018-03-12 10:49:29

标签: haskell

我的程序应该遍历给定目录中的所有文件,并使用扩展名" .vm"附加计数器到每个文件的内容。然而,它有一个错误"不能用马赫类型[]与IO"在附加。 如果有人可以帮助我,那将是geatfull

我的代码:

import System.IO
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Applicative
import Data.List
import System.Directory
import System.FilePath

main = do
    files <- getDirectoryContents "c:/program file"
    let filtered = filter ( vmExtention ) files
    [ appendFile x y| x<-filtered, y <- [0..] ]
    print filtered
    print files

vmExtention :: FilePath-> Bool
vmExtention s = 
    if ( takeExtension s )== ".vm" then True else False

3 个答案:

答案 0 :(得分:3)

[ appendFile x y| x<-filtered, y <- [0..] ]

如果[IO ()]有效(它不是),那就是appendFile x y类型的迷路列表理解。您必须使用sequence或类似的:

sequence [ appendFile x y| x<-filtered, y <- [0..] ]

但是,这不会奏效,因为y必须是String,而[0..]是无限列表,所以最终会得到

appendFile x 0
appendFile x 1
appendFile x 2
appendFile x 3
...

你想要的东西

sequence [appendFile file (show counter) | (file, counter) <- zip filtered [0..]]

答案 1 :(得分:0)

在您的代码中,files是IO操作列表([IO ()]),因此要在列表中执行IO操作,您只需调用sequence files即可。但是,您还需要更正列表理解 - 现在,它将尝试将范围[0..]中的所有整数添加到第一个文件的末尾(列表推导中的范围从左到右嵌套) ,即,给定x<-A, y<-B,对于每个x,我们从B中取a,直到B耗尽,然后取下一个x)。更好的列表理解将是

let files = [appendFile (path </> x) (show y) | zip filtered [0..] ]

请注意,您还需要将路径添加到文件名的开头(我将let path = "c:\program file"添加到主函数的开头),您需要show整数将其转换为appendFile的字符串。

答案 2 :(得分:0)

import System.IO
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Applicative
import Data.List
import System.Directory
import System.FilePath
import Debug.Trace

debug = flip trace

main = do
    let path = "/tmp/test"
    files <- getDirectoryContents path
    let filtered = filter ( vmExtention ) files
    let filteredWithIndex = zip filtered [0..]
    sequence_ [ appendFile' (path </> fp) (show i) | (fp,i) <- filteredWithIndex ]

appendFile' fp s =
  -- note that the path was relative but is now fixed
  appendFile fp s `debug` ("filepath: " ++ fp)

vmExtention :: FilePath-> Bool
vmExtention s = 
    takeExtension s == ".vm"