<div dir="ltr"><div>Hmm. David, I'm reading about io-stream now (I have never met it early), it looks very interesting. Is it the same idea as Pipe/Conduit (to "piping" data by fixed memory usage in each "processing phase")?<br><br><br></div>By the way, what do you prefer more: pipes or conduits? Snoyman said that pipes has limited design due to exceptions handling possibilities, it is true today? What is more stable, better designed, more "clean"?<br><br></div><div class="gmail_extra"><br><div class="gmail_quote">2017-05-05 22:19 GMT+03:00 David McBride <span dir="ltr"><<a href="mailto:toad3k@gmail.com" target="_blank">toad3k@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Sorry I'm having trouble understanding your english and am unfamiliar<br>
with some of the terms you are using.<br>
<br>
-- More natural is to have abstract stream of bytes. And to read only<br>
<span class="">bytes. Then to convert them into<br>
<br>
</span>There are a lot of abstractions of data in haskell. Are you looking<br>
for something like pipes, conduits, or io-streams?<br>
<br>
io-streams for example exports different ways to get an io-stream from<br>
some source.<br>
<br>
-- from / to a network<br>
socketToStreams :: Socket -> IO (InputStream ByteString, OutputStream<br>
ByteString)<br>
withFileAsInput<br>
<br>
-- various to and from files with or without automatic resource management<br>
handleToInputStream :: Handle -> IO (InputStream ByteString)<br>
<br>
-- to / from an interactive command.<br>
runInteractiveCommand :: String -> IO (OutputStream ByteString,<br>
InputStream ByteString, InputStream ByteString, ProcessHandle)<br>
<br>
Once you have an OutputStream or an InputStream, you can do whatever<br>
you want with them.<br>
<br>
-- fold an input stream into some type s, via the supplied functions.<br>
fold :: (s -> a -> s) -> s -> InputStream a -> IO s<br>
<br>
-- ensure that every byte in an input stream conforms to a supplied function.<br>
all :: (a -> Bool) -> InputStream a -> IO Bool<br>
<br>
-- zip two input streams into a single input stream with characters from each.<br>
zip :: InputStream a -> InputStream b -> IO (InputStream (a, b))<br>
<br>
-- And if you have access to such a stream, you can manipulate at a<br>
very low level if you need to<br>
read :: InputStream a -> IO (Maybe a)<br>
peek :: InputStream a -> IO (Maybe a)<br>
unRead :: a -> InputStream a -> IO ()<br>
<br>
I don't think I've used hGetContents for many years. While io-streams<br>
is the most straight forward, I personally use pipes quite a bit in my<br>
every day code.<br>
<br>
Beyond that for writing a complex datatype to a bytestring there are<br>
numerous libraries like binary and cereal which allow you to write<br>
bytes in a very exact fashion, to be put into a file or over the<br>
network if you wish.<br>
<br>
I'm not sure if I've gotten to the heart of what you are asking, but<br>
haskell provides a huge wealth of ways to access and manipulate data<br>
on every possible level and they pretty much all fit together very<br>
well, far better than similar abstractions in other languages ever<br>
could, so far as I'm aware.<br>
<div class="HOEnZb"><div class="h5"><br>
On Fri, May 5, 2017 at 2:31 PM, baa dg <<a href="mailto:aquagnu@gmail.com">aquagnu@gmail.com</a>> wrote:<br>
> This sure makes sense and all other languages follow this practice. But<br>
> nevertheless Sndfile has this `hGetContents`. And Darcs module.<br>
> But more strange for me is: it is considered that this function<br>
> (hGetContents) is sufficiently universaland meets so often. But this is the<br>
> reading from file handler which is not abstract/generic/universal. So:<br>
><br>
> - there are types which are in no way related to I/O but their modules<br>
> implements I/O functions and this is very strange<br>
> - and even more: these I/O related functions are based on concreate kind of<br>
> I/O - file handler based, which means that no ways to read these types from<br>
> SPI, I2C or any other not file-hadler-based I/O. Whether there are any<br>
> serious problems with abstraction?<br>
><br>
> More natural is to have abstract stream of bytes. And to read only bytes.<br>
> Then to convert them into Text, Sndfiles, etc, but such I/O functions can<br>
> not be in "model"-related modules (where are defined data types). And is we<br>
> will read new type from NEW INTERFACE (which has not file handler), nothing<br>
> will be broken: we will still read bytes from a stream of bytes with<br>
> abstract interface (type-class); and this stream may be bound to register<br>
> I/O port, for example, etc - not file handler. If we need such kind of I/O -<br>
> we will add something like `portGetContents` in all these modules: Text,<br>
> ByteString, Sndfile, etc ? :)<br>
><br>
> This is what I can't understand.<br>
><br>
><br>
> 2017-05-05 15:33 GMT+03:00 David McBride <<a href="mailto:toad3k@gmail.com">toad3k@gmail.com</a>>:<br>
>><br>
>> In haskell you have datatypes like String, Text, Text.Lazy,<br>
>> ByteString, etc. All of those have functions like readFile,<br>
>> writeFile, hPutStr, hGetLine (if applicable to that type). If you<br>
>> have your own type, say a Triangle, you would usually get that from<br>
>> one of the intermediate types, such as Bytestring -> Triangle.<br>
>><br>
>> It is also possible to make a class which allows you to create a<br>
>> Triangle from a variety of types, ToShape a => a -> Triangle, where<br>
>> instance ToShape ByteString.<br>
>><br>
>> For your second question. To do a complex type from say a ByteString,<br>
>> most people would use a parser combinator, perhaps something like<br>
>> attoparsec, although there are many other options. That particular<br>
>> library allows you to parse from a bytestring or from a file as<br>
>> needed. When using it on a file you might use withFile around<br>
>> parseWith and pass hGetContents as its first argument.<br>
>><br>
>> On Fri, May 5, 2017 at 5:31 AM, PY <<a href="mailto:aquagnu@gmail.com">aquagnu@gmail.com</a>> wrote:<br>
>> > Hello everyone! I'm trying to understand base idea of Haskell modules<br>
>> > architecture. In other languages, "reading from file" is placed in<br>
>> > something<br>
>> > like "io", "istream", "file", etc modules. Also most languages have a<br>
>> > concept of reading from abstract bytes streams. You read bytes from<br>
>> > something and translate them into your high level object/type/etc.<br>
>> ><br>
>> > In Haskell I see that, for example, function hGetContents exists in<br>
>> > (this<br>
>> > is my local installation):<br>
>> ><br>
>> > GHC.IO.Handle<br>
>> > System.IO<br>
>> > Data.ByteString<br>
>> > Data.ByteString.Char8<br>
>> > Data.ByteString.Lazy<br>
>> > Data.ByteString.Lazy.Char8<br>
>> > <a href="http://Data.Text.IO" rel="noreferrer" target="_blank">Data.Text.IO</a><br>
>> > <a href="http://Data.Text.Lazy.IO" rel="noreferrer" target="_blank">Data.Text.Lazy.IO</a><br>
>> > System.IO.Strict<br>
>> > Text.Pandoc.UTF8<br>
>> > Data.ListLike<br>
>> > <a href="http://Data.ListLike.IO" rel="noreferrer" target="_blank">Data.ListLike.IO</a><br>
>> > ClassyPrelude<br>
>> > Hledger.Utils.UTF8IOCompat<br>
>> > Data.IOData<br>
>> > Darcs.Util.Ratified<br>
>> > Sound.File.Sndfile<br>
>> > Sound.File.Sndfile.Buffer<br>
>> > Data.String.Class<br>
>> > Network.BufferType<br>
>> ><br>
>> > If I'll create module SuperMegaShapes with some Triangle, Rectangle,<br>
>> > Square<br>
>> > and other things, I'll create (to be consistent with Haskell-way)...<br>
>> > hGetContents there??!<br>
>> ><br>
>> > So, I have 2 questions here:<br>
>> ><br>
>> > First one: let's imagine that we have Haskell compiler for embedded. And<br>
>> > I<br>
>> > want to read Text, ByteString, Sndfile and SuperMegaShapes from... SPI.<br>
>> > There are many devices andprotocols, right? And I have not FILE HADNLER<br>
>> > for<br>
>> > most of them. So, this mean that Haskell (like simple script language)<br>
>> > supports only concept of FILE HANDLER reading?! And no other<br>
>> > ABSTRACTIONS?<br>
>> ><br>
>> > Second question is: must any new type which we plan to read/write to<br>
>> > have<br>
>> > hGetContents? What if it is packed in some tricky container? Matreshka?<br>
>> > Something else, more tricky? :) And more: what other I/O functions must<br>
>> > be<br>
>> > injected in our model definitions modules?<br>
>> ><br>
>> ><br>
>> > ===<br>
>> > Best regards<br>
>> ><br>
>> > ______________________________<wbr>_________________<br>
>> > Beginners mailing list<br>
>> > <a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
>> > <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/beginners</a><br>
>> ><br>
>> ______________________________<wbr>_________________<br>
>> Beginners mailing list<br>
>> <a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
>> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/beginners</a><br>
><br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> Beginners mailing list<br>
> <a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/beginners</a><br>
><br>
______________________________<wbr>_________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/beginners</a><br>
</div></div></blockquote></div><br></div>