I'm always in favor of providing algorithmicly better interfaces, so barring me learning that there's doe thing even better we should do , +1 :)<span></span><br><br>On Sunday, June 19, 2016, Ryan Scott <<a href="mailto:ryan.gl.scott@gmail.com">ryan.gl.scott@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">GHC 8.0 added the Data.Functor.Classes module [1] to base, and with it<br>
the Read1 and Read2 typeclasses. The current definition of Read1 is<br>
this:<br>
<br>
    class Read1 f where<br>
        liftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (f a)<br>
        liftReadList :: (Int -> ReadS a) -> ReadS [a] -> ReadS [f a]<br>
<br>
There's a pretty big problem with this definition: it uses ReadS (a<br>
synonym for String -> [(a, String)]). This sort of parser is very slow<br>
(the docs even admit as such [2]), and moreover, the actual Read<br>
typeclass on which Read1 is based tries to avoid using it whenever<br>
possible.<br>
<br>
The Read typeclass has this definition currently:<br>
<br>
    class Read a where<br>
        readsPrec    :: Int -> ReadS a<br>
        readList     :: ReadS [a]<br>
        readPrec     :: ReadPrec a<br>
        readListPrec :: ReadPrec [a]<br>
<br>
Where ReadPrec is a much more efficient parser datatype. When deriving<br>
Read instances, GHC defines them in terms of readPrec, and gives the<br>
other methods default definitions that leverage readPrec.<br>
<br>
For the sake of consistency, I propose adding analogous methods to<br>
Read1 and Read2 that use the ReadPrec datatype. For example, here is<br>
how I would change Read1:<br>
<br>
    class Read1 f where<br>
        liftReadsPrec    :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (f a)<br>
        liftReadList     :: (Int -> ReadS a) -> ReadS [a] -> ReadS [f a]<br>
        liftReadPrec     :: ReadPrec a -> ReadPrec [a] -> ReadPrec (f a)<br>
        liftReadListPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec [f a]<br>
<br>
And similarly for Read2. Here is a full gist [3] with a sketch of what<br>
the new Read1/Read2 definitions would look like, including what the<br>
default definitions of the other methods would be.<br>
<br>
Ryan S.<br>
-----<br>
[1] <a href="http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html" target="_blank">http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Functor-Classes.html</a><br>
[2] <a href="http://hackage.haskell.org/package/base-4.9.0.0/docs/Text-ParserCombinators-ReadP.html#t:ReadS" target="_blank">http://hackage.haskell.org/package/base-4.9.0.0/docs/Text-ParserCombinators-ReadP.html#t:ReadS</a><br>
[3] <a href="https://gist.github.com/RyanGlScott/7cdd11d6aa878e4229acf1a682beb1fc" target="_blank">https://gist.github.com/RyanGlScott/7cdd11d6aa878e4229acf1a682beb1fc</a><br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="javascript:;" onclick="_e(event, 'cvml', 'Libraries@haskell.org')">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote>