
On 01/30/2018 02:06 AM, Ivan Lazar Miljenovic wrote:
On 30 January 2018 at 14:48, Li-yao Xia
wrote: Hello libraries,
base contains a small combinator library for Read, but there doesn't seem to be a similar thing for Show. Offering a few more convenient helpers to avoid dealing with whitespace and especially precedence levels seems straightforward enough.
Is there an API somewhere that I missed? Has there been a proposal/discussion about this before? I'm ready to make one otherwise.
Have you looked at the ShowS-based methods? They tend to be a bit more combinator-y (though they don't cover whitespace). For example, here's the Show instance for Data.Graph.Inductive.Tree:
instance (Show a, Show b) => Show (Gr a b) where showsPrec d g = showParen (d > 10) $ showString "mkGraph " . shows (labNodes g) . showString " " . shows (labEdges g)
In fact, I meant that this API seems suboptimal. As you mentioned, we have to deal explicitly with spacing ("mkGraph ") and also precedence levels. It's not much but the UX could be streamlined further by hiding those details. (And now that I look at Text.Read again, we also have to deal with precedence there.) Flip showsPrec, precShows :: a -> Int -> ShowS, Hide its result type, type Doc = Int -> ShowS Give a combinator for constructors, showCon :: String -> Doc showCon con _ = showString con and one for function application, showApp :: Doc -> Doc -> Doc showApp f x d = showParen (d > appPrec) (f appPrec . showSpace . x (appPrec + 1)) where appPrec = 10 infixl 8 `showApp` An instance would thus look like ... precShows g = showCon "mkGraph" `showApp` precShows (labNodes g) `showApp` precShows (labEdges g) There are also combinators for infix constructors and records to be written. These would cover the overwhelming majority of use cases where we must handwrite Show [citation needed]. What do you think of that? Doesn't that look better? Li-yao