Proposal: Add IsString instance for (Maybe a) to base

Gabriel Gonzalez gabriel439 at gmail.com
Fri Jul 12 13:25:35 CEST 2013


On 07/12/2013 02:03 AM, John Lato wrote:
> In all seriousness, I'm not that fond of the proposal myself.  I just 
> wanted to argue the other side because nobody else was.

I appreciate that! :)  I, too, enjoy playing the devil's advocate.

> But so far, I've seen two main arguments against the proposal:
>
> 1.  IsString is for things that are notionally some sort of string.
> 2.  It makes the types more confusing.
>
> The second seems like a weak argument to me.  First off, the proposal 
> seems very similar to the recent generalization of Prelude.map, which 
> had a great deal of support.

There is a difference between type-classing `fmap` and type-classing 
string literals.  `fmap` has laws governing its behavior that preserve a 
certain intuition and keep the instance writer on the straight and 
narrow path.

Speaking of which, it would be an improvement if `fromString` instances 
some sort of functor laws, even if they were not totally rigorous and 
the destination category is changing on an instance-by-instance basis.  
For example, the `String`/`Text`/`ByteString` instances for `fromString` 
should obey (or *mostly* obey) these laws:

     fromString (str1 <> str2) = fromString str1 <> fromString str2 :: 
Vector Char/Text/ByteString
     fromString mempty = mempty

Whereas the parser instances you mentioned would probably satisfy the 
following laws, at least for the `attoparsec` library, if the `string` 
parser returned `()` instead of the parsed string:

     fromString (str1 <> str2) = fromString str1 >> fromString str2 :: 
Parser ()
     fromString mempty = return ()

I think the treatment of `fromString` as a functor from the String 
monoid to some other category is the closest theoretical statement of 
your intuition that an `IsString` instance should "represent" a `String`.

Notice that this treatment actually rejects the proposed `Maybe` 
instance, since:

fromString mempty /= (mempty :: (IsString a) => Maybe a)

`mempty` should evaluate to `Nothing` in that context, but the proposal 
suggests it should be `Just ""`.  You could argue that the current 
`Monoid` instance for `Maybe` is the wrong one and that `Just ""` is the 
correct identity, but then that would just confirm that the correct 
behavior is underspecified in this case and it is better to not let the 
programmer guess which behavior we meant.



More information about the Libraries mailing list