On Wed, 2014-07-02 at 15:31 -0700, Gabriel Gonzalez wrote:
> I think the interface I would recommend would be:
>
> hash :: (HashAlgorithm a, Monad m) => Producer ByteString m r ->
> Producer ByteString m (Digest, r)
>
> I noticed your version has two `Producer` layers. What's the role of
> the second `Producer`?
Good question :-) I expected to be able to write the function according
to the type you point out above, but when I wrote the thing, GHC
insisted the base `Producer` was required, and I tend to trust GHC when
it tells me such things.
Now, since you made the same remark, and I tend to trust you as well
(;-)), I went back to the code and figured out all I need is a `lift`...
So, first API change:
hash :: (HashAlgorithm a, Monad m)
=> Producer ByteString m r
-> Producer ByteString m (r, Digest a)
Much better!
Now I'm wondering whether I'm overlooking any function in the Pipes
library which does what my internal function does:
hashInternal :: Monad m
=> (a -> b -> a)
-> a
-> Producer b m r
-> Producer b m (r, a)
hashInternal f = loop
where
loop !ctx p =
lift (next p) >>=
either
(\r -> return (r, ctx))
(\(b, p') -> yield b >> loop (f ctx b) p')
This seems like a fairly reasonable/common thing to do, no (modulo the
strictness, could be pushed into `f`)?
Thanks,
Nicolas
>
> On 7/2/14, 2:49 PM, Nicolas Trangez wrote:
> > All,
> >
> > Recently I was looking for a way to calculate the SHA256 hash of a
> > stream of ByteStrings, but not only calculate this hash: also pass on
> > the stream so it could be stored to a file (use-case: receiving data
> > from a socket, which needs to be saved to a file, named after a hash of
> > the content, then returning this 'name' to the client).
> >
> > I couldn't find any such library of-the-shelve in the Pipes ecosystem,
> > so I tried to implement something myself (with some help from IRC), and
> > just now pushed a first version of the code to GitHub.
> >
> > So, consider this a 'request for feedback/review' :-)
> >
> > The hashing itself is based on the 'cryptohash' library.
> >
> > There are 2 interfaces:
> > - One where a (strict or lazy) ByteString Producer can be wrapped,
> > resulting in a new Producer which will yield the exact same values as
> > the original one, but tupling the result of the original Producer with a
> > digest. E.g.
> >
> > hash :: (HashAlgorithm a, Monad m)
> > => Producer ByteString (Producer ByteString m) r
> > -> Producer ByteString m (r, Digest a)
> >
> > - One which acts as a real 'Pipe' which passes along every (strict or
> > lazy) ByteString it receives, and updates a hashing Context kept in a
> > State layer of the monad stack. E.g.
> >
> > hashPipe :: (HashAlgorithm a, MonadState (Context a) m)
> > => Pipe ByteString ByteString m r
> >
> >
> > These have some variants: working over streams of strict or lazy
> > bytestrings, requiring type inference to determine the hash type, or an
> > explicit value, or allowing to pass in an existing context (e.g.
> > generated by another stream before).
> >
> > Code @ https://github.com/NicolasT/pipes-cryptohash/
> >
> > Please let me know if you think the API could be enhanced, I'm doing
> > something utterly wrong,...
> >
> > Thanks!
> >
> > Nicolas
> >
>
--
You received this message because you are subscribed to the Google Groups
"Haskell Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].