default instance for IsString

Previous Topic Next Topic
classic Classic list List threaded Threaded
62 messages Options
Reply | Threaded
Open this post in threaded view
Report Content as Inappropriate

Re: default instance for IsString

Tyson Whitehead
On April 25, 2012 12:20:16 Johan Tibell wrote:
> On Wed, Apr 25, 2012 at 8:19 AM, Tyson Whitehead <[hidden email]>
> > Is there a technical reason this couldn't be done?  The Haskell report
> > only says doing this is not part of haskell.  It doesn't say why.
> I think the problem is incoherence, what if the same Map value got
> used with two different instances of Int?

I'm not sure I follow how allowing control over importing of instances could
allow a programmer to define multiple instances for the same types.

I would have expected this to result in a link time error as a product of
multiple declerations (something like a multiple symbol definition) regardless
of whether any module brings it into scope as a possible candidate for use.

Cheers!  -Tyson

Glasgow-haskell-users mailing list
[hidden email]
Reply | Threaded
Open this post in threaded view
Report Content as Inappropriate

Re: default instance for IsString

Joachim Breitner-2
In reply to this post by Joachim Breitner-2

Am Mittwoch, den 25.04.2012, 21:57 +0100 schrieb Joachim Breitner:

> Am Mittwoch, den 25.04.2012, 11:15 +0300 schrieb Yitzchak Gale:
> > The only reason I don't like using OverloadedStrings
> > for typing string literals as Text and ByteString
> > is that when you turn on OverloadedStrings, you turn
> > it on for all types, not just Text and ByteString.
> > I don't want to be forced to do that. Because
> > all other uses of OverloadedStrings that I have
> > seen, and there are many, are ill-advised in my
> > opinion. They all should have been quasiquoters.
> another option, quick idea from a pub: Make OverloadedStrings work with
> re-bindable syntax (←needs GHC change, probably) and redefine fromString
> as you want. E.g, if you want to use alwas Text, just define
> fromText :: String -> Text
> in your module (and do not import the IsString method).
actually, this already works somewhat. Take this module:

        {-# LANGUAGE OverloadedStrings, RebindableSyntax #-}
        import Prelude
        data MyStringType = AnyString deriving Eq
        fromString :: String -> MyStringType
        fromString _ = AnyString
        test = "test"
and see how GHC uses the fromString that I defined; it affects both the
type of test and its value:

Prelude> :r
[1 of 1] Compiling Main             ( /tmp/Test.hs, interpreted )
Ok, modules loaded: Main.
*Main> :t test
test :: MyStringType
*Main> test == AnyString

So what is needed for the OP to be happy seems to be either a way to
enable RebindableSytanx _only_ for fromString, or to have a variant of
OverloadedStrings that takes fromString from the module scope. Then he
could define a monomorphic fromString (as I have done) or define its own
typeclass that defines fromString only for desirable types.

With this class definition, declaring IsString instances as save becomes
a one-liner:

        {-# LANGUAGE OverloadedStrings, RebindableSyntax, FlexibleInstances #-}
        import Prelude
        import qualified GHC.Exts
        import Data.Text
        class GHC.Exts.IsString a => SafeIsString a where
            fromString :: String -> a
            fromString = GHC.Exts.fromString
        instance SafeIsString String
        instance SafeIsString Text
        test1 :: String
        test1 = "test1"
        test2 :: Text
        test2 = "test2"

Prelude> :r
[1 of 1] Compiling Main             ( /tmp/Test.hs, interpreted )
Ok, modules loaded: Main.
*Main> :t (test1,test2)
(test1,test2) :: (String, Text)
*Main> (test1,test2)
Loading package array- ... linking ... done.
Loading package bytestring- ... linking ... done.
Loading package deepseq- ... linking ... done.
Loading package text- ... linking ... done.

Note that if I’d also add

        import Data.ByteString.Char8
        test3 :: ByteString
        test3 = "test3"

I’d get
*Main> :r
[1 of 1] Compiling Main             ( /tmp/Test.hs, interpreted )

    No instance for (SafeIsString ByteString)
      arising from the literal `"test3"'
    Possible fix:
      add an instance declaration for (SafeIsString ByteString)
    In the expression: "test3"
    In an equation for `test3': test3 = "test3"
Failed, modules loaded: none.

so I am guaranteed not to accidentally call a fromString from an
instance that I have not allowed.


PS: Personally, I don’t really think there is a big problem, but
anyways, here is a solution :-)

Joachim "nomeata" Breitner
  [hidden email]  |  [hidden email]  |  GPG: 0x4743206C
  xmpp: [hidden email] | http://www.joachim-breitner.de/

Glasgow-haskell-users mailing list
[hidden email]

signature.asc (205 bytes) Download Attachment