2012-08-16 92 views
2

我有一个功能f :: ByteString -> String,需要一个Sink ByteString (ResourceT IO)。 我如何得到这个?将功能提升到导管槽

不幸的是,该文档是不是非常有帮助?

+0

你想要接收器做什么? – dave4420 2012-08-16 13:15:31

+0

'Sink ByteString(ResourceT IO)'不是一种类型。你的意思是'Sink ByteString(ResourceT IO)String'? – dave4420 2012-08-16 13:20:09

+0

是的,对不起。接收器应该在Yesod文件上传中使用fileSource的结果,并计算其md5哈希(使用'Yesod.Static.base64md5')。 – mrueg 2012-08-16 15:41:06

回答

1

我不知道为什么你需要什么在这个管道做resourceT。

为了将它全部返回到由所有小字节串组成的一个大字符串中,您必须累积片段一段时间,然后将其返回到最后。

fSink :: Monad m => Sink ByteString m String 
fSink = go [] 
    where 
    go accum = do 
     x <- await 
     case x of 
     Nothing -> return . f . B.concat . reverse $ accum 
     Just x' -> go (x':accum) 
+0

谢谢你的回答。对ResourceT的要求仅仅是由于Yesod从版本1.1开始处理文件上传的方式。 你得到一个'Source(ResourceT IO)ByteString'而不是'ByteString',就像它在Yesod 1.0中一样。 – mrueg 2012-08-16 15:08:42

3

这里是解决问题的通用解决方案:让我们采取任何功能i -> r,其中iMonoid,并通过与mappend折叠所有await S的能把它变成一个水槽。

import Data.Conduit 
import Data.Conduit.List as CL 
import Data.Monoid 

monoidFold :: (Monoid i, Monad m) => (i -> r) -> Sink i m r 
monoidFold f = f `fmap` CL.fold mappend mempty 

由于ByteStringMonoid,您的ByteString -> String类型的函数可以被用作的monoidFold参数。

myMD5 :: ByteString -> String 
monoidFold myMD5 :: Monad m => Sink ByteString m String 
+0

非常有教育意义,谢谢 – fp4me 2012-08-16 18:04:54