Yesod handlers, content of POSTed files

给你一囗甜甜゛ 提交于 2019-12-08 11:14:54

问题


while the following code:

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

seems to work (at least can I "liftIO $ print fc), splitting it off to a function for iterating doesn't:

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

or even with a lambda function:

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

in the Handler it gives me a type error I don't understand.

Where's my fault -- liked to generate content for database import from the file's lines (and to learn some more Haskell, of course).


回答1:


You have

fileName :: FileInfo -> Text

so you can't directly use fileName in a do-block like

fn <- fileName f

That would need to be a let-binding

let fn = fileName f

The next thing is what makes process :: [FileInfo] -> [String] impossible(1),

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

so with

fc <- lift $ fileSource f $$ consume

you are in a do-block whose Monad is a MonadIO, and you can't get out of a Monad that can wrap arbitrary IO-actions, just like you can't get out of IO itself.

What you can have is

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)

or, more succinctly,

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

and then

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

(1) Barring unsafePerformIO.



来源:https://stackoverflow.com/questions/14855617/yesod-handlers-content-of-posted-files

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!