0

而下面的代码:

postImportR = do
    fi <- lookupFiles "file"
    fc <- lift $ fileSource (fi !! 0) $$ consume

似乎可以工作(至少我可以“liftIO $ print fc”),将其拆分为一个迭代函数不会:

process :: [FileInfo] -> [String]
process [] = []
process (f:r) = do
    fn <- fileName f
    fc <- lift $ fileSource f $$ consume
    ([fn] : (process r))

postImportR = do
    fi <- lookupFiles "file"
    process fi

甚至使用 lambda 函数:

files <- L.map (\f -> (fileName f, lift $ fileSource f $$ consume)) fi

在处理程序中,它给了我一个我不明白的类型错误。

我的错在哪里——喜欢从文件的行中生成用于数据库导入的内容(当然,还要学习更多 Haskell)。

4

1 回答 1

1

你有

fileName :: FileInfo -> Text

所以你不能直接fileName在 do-block 中使用

fn <- fileName f

那将需要是一个 let-binding

let fn = fileName f

接下来是什么使process :: [FileInfo] -> [String]不可能(1)

fileSource :: FileInfo -> Source (ResourceT IO) ByteString

所以与

fc <- lift $ fileSource f $$ consume

你在一个 do-block中,它Monad是 a MonadIO,你无法摆脱一个Monad可以包装任意IO-actions 的 a ,就像你无法摆脱IO它自己一样。

你可以拥有的是

process :: (SomeFiendishConstraint m) => [FileInfo] -> m [Text]
process [] = return []
process (f:r) = do
    let fn = fileName f
    lift $ fileSource f $$ consume
    fs <- process r
    return (fn : fs)

或者,更简洁地说,

process = mapM (\f -> lift $ fileSource f $$ consume >> return fileName f)

接着

postImportR = do
    fi <- lookupFiles "file"
    process fi

(1)禁止unsafePerformIO

于 2013-02-13T16:44:11.147 回答