<div dir="ltr"><div>David, thank you for comprehensive answers!<br></div>Have a nice day.<br></div><div class="gmail_extra"><br><div class="gmail_quote">2017-05-06 13:10 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">I'd say that haskell depends more on its libraries than most other<br>
languages because they kind of get better over time and a lot of times<br>
the better libraries are not at a beginner level of skill.<br>
<br>
As for hGetContents not being generic over its types, people have<br>
actually written typeclasses for that purpose.  See<br>
<a href="http://hackage.haskell.org/package/ListLike-4.5.1/docs/Data-ListLike.html#v:hGetContents" rel="noreferrer" target="_blank">http://hackage.haskell.org/<wbr>package/ListLike-4.5.1/docs/<wbr>Data-ListLike.html#v:<wbr>hGetContents</a><br>
it is just that it is not in the standard library.  The problem with<br>
having everything typeclassed is that it makes it so that you have to<br>
fix all the types before your code will compile.  There are a lot of<br>
people who believe that some of the list functions like length should<br>
not be generic in Prelude because it's difficult to get the hang of<br>
when you first start learning haskell.  I'm not one of them, but I<br>
understand what they are getting at.<br>
<br>
I personally use pipes, but over the years they've more or less<br>
reached feature parity.  Pipes has a few minor things over conduits,<br>
conduits is slightly easier to use.  You can convert between the two<br>
fairly easily in code.  Which you use is up to you.<br>
<div class="HOEnZb"><div class="h5"><br>
On Sat, May 6, 2017 at 1:02 AM, baa dg <<a href="mailto:aquagnu@gmail.com">aquagnu@gmail.com</a>> wrote:<br>
> Hmm. David, I'm reading about io-stream now (I have never met it early), it<br>
> looks very interesting. Is it the same idea as Pipe/Conduit (to "piping"<br>
> data by fixed memory usage in each "processing phase")?<br>
><br>
><br>
> By the way, what do you prefer more: pipes or conduits? Snoyman said that<br>
> pipes has limited design due to exceptions handling possibilities, it is<br>
> true today? What is more stable, better designed, more "clean"?<br>
><br>
><br>
> 2017-05-05 22:19 GMT+03:00 David McBride <<a href="mailto:toad3k@gmail.com">toad3k@gmail.com</a>>:<br>
>><br>
>> 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>
>> bytes. Then to convert them into<br>
>><br>
>> 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<br>
>> function.<br>
>> all :: (a -> Bool) -> InputStream a -> IO Bool<br>
>><br>
>> -- zip two input streams into a single input stream with characters from<br>
>> 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>
>><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<br>
>> > 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<br>
>> > of<br>
>> > I/O - file handler based, which means that no ways to read these types<br>
>> > 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<br>
>> > bytes.<br>
>> > Then to convert them into Text, Sndfiles, etc, but such I/O functions<br>
>> > can<br>
>> > not be in "model"-related modules (where are defined data types). And is<br>
>> > we<br>
>> > will read new type from NEW INTERFACE (which has not file handler),<br>
>> > 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<br>
>> > register<br>
>> > I/O port, for example, etc - not file handler. If we need such kind of<br>
>> > 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.<br>
>> >> > And<br>
>> >> > I<br>
>> >> > want to read Text, ByteString, Sndfile and SuperMegaShapes from...<br>
>> >> > SPI.<br>
>> >> > There are many devices andprotocols, right? And I have not FILE<br>
>> >> > HADNLER<br>
>> >> > for<br>
>> >> > most of them. So, this mean that Haskell (like simple script<br>
>> >> > 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?<br>
>> >> > Matreshka?<br>
>> >> > Something else, more tricky? :) And more: what other I/O functions<br>
>> >> > 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>
><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>