Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extension OverloadedString doesn't fully infer IsString. Why? Or what am I missing?

Tags:

haskell

ghc 7.6.3

is quite upset for some code i'm trying to compile

the error is

No instance for (Data.String.IsString t3)
arising from the literal `"meh"'
The type variable `t3' is ambiguous

i don't understand. it's a literal. what is ambiguous? why can't it infer this as a string?

this is coming in a call like

foo bar "meh"

where foo doesn't require the second argument to be anything in particular (it must satisfy some typeclass, and it does for the particular combos it is getting.)

i'll note i can fix this error by changing the call to

foo bar ("meh" :: String)

which is clearly insane.

-- edit

maybe it has nothing to do with overloadedStrings

i can "reproduce" this error just with

data B a where
    Foo :: a -> B A

then in GHCi writing simply

Foo "ok"

(clearly this fails as i'm not deriving Show, but why do i also get

No instance for (Data.String.IsString a0)
    arising from the literal `"ok"'
  The type variable `a0' is ambiguous
  ...

? what's going on here? what does this mean?)

like image 548
goingSpain Avatar asked Oct 18 '14 12:10

goingSpain


1 Answers

it's a literal. what is ambiguous? why can't it infer this as a string?

When you use OverloadedStrings "meh" is not a literal String. It's a literal polymorphic value of type IsString a => a. Its type can't be inferred as String because it could also be used as a lazy ByteString, strict ByteString, Text, etc..

foo doesn't require the second argument to be anything in particular

If foo doesn't require the second argument to be anything in particular how does the type checker know the argument to foo should be a String, rather than a Text, etc.?

i'll note i can fix this error by changing the call to foo bar ("meh" :: String) which is clearly insane.

Now you are telling the type checker which specific type you want for "meh".

maybe it has nothing to do with overloadedStrings

It is exactly to do with OverloadedStrings. Personally I recommend not using OverloadedStrings and just using Data.String.fromString precisely because of the confusing behaviour you are seeing.

i can "reproduce" this error just with ... what's going on here? what does this mean?

Here's a concrete example of the ambiguity.

{-# LANGUAGE OverloadedStrings, FlexibleInstances #-}

import Data.Text

class Foo a where
  foo :: a -> String

instance Foo String where
  foo _ = "String"

instance Foo Text where
  foo _ = "Text"

main :: IO ()
main = print (foo "meh")

What should main print? It depends on the type of "meh". What type did the user want for "meh"? With OverloadedStrings on, there's no way to know.

like image 69
Tom Ellis Avatar answered Oct 31 '22 01:10

Tom Ellis