Extension OverloadedString doesn't fully infer IsString. Why? Or what am I missing? - 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?)

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.

Related

Matching on a particular type of a parametric type

I'm trying to work with an external library that has provided a parametric type like this:
data ParametricType a = TypeConstructor a
I have a typeclass, something like this:
class GetsString a where
getString :: a -> String
and I'd like to execute some code if ParametricType's a is a specific type. I've tried narrowing the type when instantiating the typeclass:
data HoldsString = HoldsString String
instance GetsString (ParametricType HoldsString) where
getString (TypeConstructor (HoldsString str)) = str
which errors with Illegal instance declaration for‘GetsString (ParametricType HoldsString)’(All instance types must be of the form (T a1 ... an)
and I've tried pattern matching on the type:
instance GetsString (ParametricType a) where
getString (TypeConstructor (HoldsString str)) = str
for which I receive Couldn't match expected type ‘a’ with actual type ‘HoldsString’‘a’ is a rigid type variable bound by the instance declaration.
Is there a way to do this, or am I conceptually on the wrong track here?
You're just missing the FlexibleInstances extension. Put {-# LANGUAGE FlexibleInstances #-} at the top of your file, or do :set -XFlexibleInstances if you're typing into GHCi directly, and then your first attempt will work.

Is there a way to refer directly to typeclass instances in Haskell?

The benefit of this could be to store certain metadata about the type in a canonical location. Sometimes, it isn't convenient to have a value of the type before using some instance methods on it; For instance if I have:
class Foo a where
foo :: String
foo = "Foo"
This is not actually valid Haskell. Instead it seems I have to have something like:
class Foo a where
foo :: a -> String
foo = const "Foo"
and now foo will actually have type Foo a => a -> String, but I would actually like to be able to do something like having a foo with type Instance Foo -> String. For this to be useful in some contexts, it might be also necessary to iterate over all (in-scope?) instances, or in other contexts, to be able to specifically materialize an instance for a given type.
I guess the issue is that instances and typeclasses are not first-class entities in Haskell?
The "old school" way of doing it is providing a "dummy" parameter whose purpose is nothing but helping the compiler find the appropriate instance. In this world, your class would look something like:
data Dummy a = Dummy
class Foo a where
foo :: Dummy a -> String
-- usage:
boolFoo = foo (Dummy :: Dummy Bool)
In fact, this trick was so ubiquitous that the Dummy type was semi-standardized as Data.Proxy.
But in modern GHC there is a better way: TypeApplications.
With this extension enabled, you can just straight up specify the type when calling the class method:
class Foo a where
foo :: String
boolFoo = foo #Bool
(this doesn't only work for class methods; it will work with any generic function, but be careful with the order of type parameters!)
You may also need to enable AllowAmbiguousTypes in order to declare such class. Though I'm not sure I remember this correctly, and I don't have a computer handy to check.
The old way (which I still prefer) is to use a proxy.
import Data.Proxy
class Foo a where
foo :: Proxy a -> String
instance Foo FancyPants where
foo _ = "a fancypants instance"
fooString :: String
fooString = foo (Proxy :: Proxy FancyPants)
So we didn't actually need a value of type FancyPants to use foo, all we needed is a value of Proxy FancyPants -- but you can create proxies of any type you want. This can be done in a polymorphic context too; usually it requires the use of the ScopedTypeVariables extension.
The new way is to use the TypeApplications and AllowAmbiguousTypes extension:
{-# LANGUAGE TypeApplications, AllowAmbiguousTypes #-}
class Foo a where
foo :: String
instance Foo FancyPants where
foo = "a fancypants instance"
fooString :: String
fooString = foo #FancyPants
Which looks nicer, but working with it in practice tends to be more irritating for a reason I can't quite put my finger on.
Did that answer the question?

Pattern bindings for existential constructors

While writing Haskell as a programmer that had exposure to Lisp before, something odd came to my attention, which I failed to understand.
This compiles fine:
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ExistentialQuantification #-}
data Foo = forall a. Show a => Foo { getFoo :: a }
showfoo :: Foo -> String
showfoo Foo{getFoo} = do
show getFoo
whereas this fails:
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ExistentialQuantification #-}
data Foo = forall a. Show a => Foo { getFoo :: a }
showfoo :: Foo -> String
showfoo foo = do
let Foo{getFoo} = foo
show getFoo
To me it's not obvious why the second snippet fails.
The question would be:
Do I miss something or stems this behaviour from the fact that haskell is not homoiconic?
My reasoning is, given that:
Haskell needs to implement record pattern matching as a compiler extension, because of it's choice to use syntax rather than data.
Matching in a function head or in a let clause are two special cases.
It is difficult to understand those special cases, as they cannot be either implemented nor looked up directly in the language itself.
As an effect of this, consistent behaviour throughout the language is not guaranteed. Especially together with additional compiler extensions, as per example.
ps: compiler error:
error:
• My brain just exploded
I can't handle pattern bindings for existential or GADT data constructors.
Instead, use a case-expression, or do-notation, to unpack the constructor.
• In the pattern: Foo {getFoo}
In a pattern binding: Foo {getFoo} = foo
In the expression:
do { let Foo {getFoo} = foo;
show getFoo }
edit:
A different compiler version gives this error for the same problem
* Couldn't match expected type `p' with actual type `a'
because type variable `a' would escape its scope
This (rigid, skolem) type variable is bound by
a pattern with constructor: Foo :: forall a. Show a => a -> Foo
Do I miss something or stems this behaviour from the fact that haskell is not homoiconic?
No. Homoiconicity is a red herring: every language is homoiconic with its source text and its AST1, and indeed, Haskell is implemented internally as a series of desugaring passes between various intermediate languages.
The real problem is that let...in and case...of just have fundamentally different semantics, which is intentional. Pattern-matching with case...of is strict, in the sense that it forces the evaluation of the scrutinee in order to choose which RHS to evaluate, but pattern bindings in a let...in form are lazy. In that sense, let p = e1 in e2 is actually most similar to case e1 of ~p -> e2 (note the lazy pattern match using ~!), which produces a similar, albeit distinct, error message:
ghci> case undefined of { ~Foo{getFoo} -> show getFoo }
<interactive>:5:22: error:
• An existential or GADT data constructor cannot be used
inside a lazy (~) pattern
• In the pattern: Foo {getFoo}
In the pattern: ~Foo {getFoo}
In a case alternative: ~Foo {getFoo} -> show getFoo
This is explained in more detail in the answer to Odd ghc error message, "My brain just exploded"?.
1If this doesn’t satisfy you, note that Haskell is homoiconic in the sense that most Lispers use the word, since it supports an analog to Lisp’s quote operator in the form of [| ... |] quotation brackets, which are part of Template Haskell.
I thought about this a bit and albeit the behaviour seems odd at first, after some thinking I guess one can justify it perhaps thus:
Say I take your second (failing) example and after some massaging and value replacements I reduce it to this:
data Foo = forall a. Show a => Foo { getFoo :: a }
main::IO()
main = do
let Foo x = Foo (5::Int)
putStrLn $ show x
which produces the error:
Couldn't match expected type ‘p’ with actual type ‘a’ because type variable ‘a’ would escape its scope
if the pattern matching would be allowed, what would be the type of x? well.. the type would be of course Int. However the definition of Foo says that the type of the getFoo field is any type that is an instance of Show. An Int is an instance of Show, but it is not any type.. it is a specific one.. in this regard, the actual specific type of the value wrapped in that Foo would become "visible" (i.e. escape) and thus violate our explicit guarantee that forall a . Show a =>...
If we now look at a version of the code that works by using a pattern match in the function declaration:
data Foo = forall a . Show a => Foo { getFoo :: !a }
unfoo :: Foo -> String
unfoo Foo{..} = show getFoo
main :: IO ()
main = do
putStrLn . unfoo $ Foo (5::Int)
Looking at the unfoo function we see that there is nothing there saying that the type inside of the Foo is any specific type.. (an Int or otherwise) .. in the scope of that function all we have is the original guarantee that getFoo can be of any type which is an instance of Show. The actual type of the wrapped value remains hidden and unknowable so there are no violations of any type guarantees and happiness ensues.
PS: I forgot to mention that the Int bit was of course an example.. in your case, the type of the getFoo field inside of the foo value is of type a but this is a specific (non existential) type to which GHC's type inference is referring to (and not the existential a in the type declaration).. I just came up with an example with a specific Int type so that it would be easier and more intuitive to understand.

How does `-XOverloadedStrings` work? (in Yesod)

I'm following Yesod tutorials from their official yesod book. (http://www.yesodweb.com/book/basics)
Unfortunately their tutorials on the book won't work, worse is that its output is very cryptic message about types not mathcing that took me quite a while to understand. Here's their original code and error message which is produced by the code:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Yesod
data Links = Links
mkYesod "Links" [parseRoutes|
/ HomeR GET
|]
instance Yesod Links
getHomeR = return $ object ["msg" .= "Hello World"]
main :: IO ()
main = warp 3000 Links
error:
helloworld2.hs:18:36:
No instance for (ToJSON a0) arising from a use of ‘.=’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance ToJSON a => ToJSON (Control.Applicative.Const a b)
-- Defined in ‘Data.Aeson.Compat’
instance ToJSON (Data.Proxy.Proxy a)
-- Defined in ‘Data.Aeson.Compat’
instance ToJSON Data.Version.Version
-- Defined in ‘Data.Aeson.Compat’
...plus 7 others
In the expression: "msg" .= "Hello World"
In the first argument of ‘object’, namely
‘["msg" .= "Hello World"]’
In the second argument of ‘($)’, namely
‘object ["msg" .= "Hello World"]’
helloworld2.hs:18:40:
No instance for (Data.String.IsString a0)
arising from the literal ‘"Hello World"’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Data.String.IsString Value
-- Defined in ‘aeson-0.9.0.1:Data.Aeson.Types.Internal’
instance (a ~ Data.ByteString.Internal.ByteString) =>
Data.String.IsString
(attoparsec-0.13.0.1:Data.Attoparsec.ByteString.Internal.Parser a)
-- Defined in ‘Data.Attoparsec.ByteString.Char8’
instance (a ~ Data.Text.Internal.Text) =>
Data.String.IsString
(attoparsec-0.13.0.1:Data.Attoparsec.Text.Internal.Parser a)
-- Defined in ‘attoparsec-0.13.0.1:Data.Attoparsec.Text.Internal’
...plus 9 others
In the second argument of ‘(.=)’, namely ‘"Hello World"’
In the expression: "msg" .= "Hello World"
In the first argument of ‘object’, namely
‘["msg" .= "Hello World"]’
it seems object ["msg" .= "Hello World"] is the problem. GHC doesn't understand what are types of "msg" and "Hello World", and can't build a JSON object out of them. I had to make their types explicit, that:
import Data.Text (Text)
getHomeR = return $ object [("msg" :: Text) .= ("Hello World" :: Text)]
it seems Aeson has toJSON instances for Text type, and I've heard that most of the text-processing codes use Text type, not String ([Char]) for efficiency reasons. But wouldn't it be nice, if every double-quoted code ("msg", "Hello World") is parsed as Text instead of String automatically? I've thought the OverloadedStrings pragma tells the compiler to do exactly that("overload" the strings into Text), but above errors without type signature indicates that I was wrong.
of course, If I have to give :: Text type signature for every string I write for output it would be very tedious and cumbersome - is there any solution for this, or is it me just don't understand enough to write Haskell and Yesod codes?
When you use OverloadedStrings, explicit strings are treated in a similar way to explicit numbers. So
x = "foo"
is desugared into
x = fromString "foo"
The IsString class defines the "fromString" function, so now all the type checker knows is that
x :: (IsString a) => a
So this is why the compiler is complaining that the type is ambiguous. There are several different string types with a ToJSON instance, and the compiler is complaining that it doesn't know which one to pick.
The only solutions, I'm afraid, are to lose the OverloadedStrings or to put in explicit type annotations to tell the compiler which instance to pick.
On String versus Text: efficiency is not a particularly big issue when you are using short constant strings like this. If you are processing text in bulk then its a bigger issue, and also the Haskell concept of String = [Char] breaks down in some languages. Text handles these properly, but String doesn't. So if you ever need to internationalise your code then String can present you with obscure problems when you try to do things like capitalise words.
The JSON code snippet you're looking at does work correctly straight out of the book. There's an additional pragma at the top of it that's missing from your code:
{-# LANGUAGE ExtendedDefaultRules #-}
I'm not a huge fan of the code snippet doing that, since I'm pretty sure people don't use that pragma in production code. It would be more typical to write the code like this:
getHomeR = return $ object ["msg" .= ("Hello World" :: String)]
Note that GHCi uses ExtendedDefaultRules to make it easier to enter expressions into the REPL without having to specify their type. If you type object ["msg" .= "Hello World"] into GHCi it'll tell you what it's defaulting to:
ghci > object ["msg" .= "Hello World"]
<interactive>:2:18: Warning:
Defaulting the following constraint(s) to type ‘String’
(IsString a0)
arising from the literal ‘"Hello World"’ at <interactive>:2:18-30
(ToJSON a0) arising from a use of ‘.=’ at <interactive>:2:15-16
In the second argument of ‘(.=)’, namely ‘"Hello World"’
In the expression: "msg" .= "Hello World"
In the first argument of ‘object’, namely
‘["msg" .= "Hello World"]’
<interactive>:2:18: Warning:
Defaulting the following constraint(s) to type ‘String’
(IsString a0)
arising from the literal ‘"Hello World"’ at <interactive>:2:18-30
(ToJSON a0) arising from a use of ‘.=’ at <interactive>:2:15-16
In the second argument of ‘(.=)’, namely ‘"Hello World"’
In the expression: "msg" .= "Hello World"
In the first argument of ‘object’, namely
‘["msg" .= "Hello World"]’
Object (fromList [("msg",String "Hello World")])
object takes a list of Pair values as argument. Pair is type Pair = (Text, Value) and it is an instance of tye KeyValue typeclass, which provides the convenience constructor (.=) :: ToJSON v => Text -> v -> kv.
The problem is as follows: .= requires the value type to have a ToJSON instance, but doesn't force the caller into any concrete type.
Meanwhile, the fromString function from IsString is overloaded on its return type: fromString :: String -> a. The precise implementation to call is determined from the return type. When OverloadedStrings is used, fromString is called implicitly for string literals.
If we feed directly the result of fromString as the value argument of .=, the compiler doesn't have enough information to assing a concrete type to the value. Should it create a Text value and convert it to json? Or perhaps create a ByteString instead and convert it to json? The problem is similar to ambiguous compositions like show . read.
Personally, instead of using type annotations I would solve the ambiguity by wrapping the string literals using the String constructor of the Value type. It tells the compiler that the literal will be Text, and of course Value is an instance of ToJSON. This is a bit less verbose than type annotations:
foo :: Value
foo = object ["foo" .= String "faa"]
You could also define a specialization of .= that took a concrete Text as the value:
(.=|) :: KeyValue kv => Text -> Text -> kv
(.=|) = (.=)
foo :: Value
foo = object ["foo" .=| "faa"]

Ambiguous type variable `p0' in the constraints

I get the error
Ambiguous type variable `p0' in the constraints:
(Show p0) arising from a use of `print' at cwqr_0003.hs:31:6-10
(Ord p0) arising from a use of `PSQ.lookup'
from the code below.
I have no idea how to analyze this. Could this be a problem in GHC or in one of the modules?
If I try putStr in place of print then I get an error related to the expected type being a string rather then maybe p0. When I try fromMaybe it gives me an error related to the default value literal zero that I send to fromMaybe
import qualified Data.PSQueue as PSQ
import Data.Maybe
import Data.Label
import Control.Category
import Prelude hiding ((.))
--some tested code omitted here
let r = PSQ.lookup test' q
--putStr (show (r :: String))
print (r)
The error message actually means exactly what it says: You have an ambiguous type. How does that happen? Usually, because you have something that produces a polymorphic result, then apply a function that takes a polymorphic argument to that result, such that the intermediate value's type is unknown.
In simple polymorphic types, the ambiguity doesn't matter: If you produce a list of something, then take the length, we don't need to know what the type of the list elements is.
If the ambiguity involves using a type class such as Show, however--which print does--GHC is stuck, because it has no way to know what instance it should pick.
Sometimes this can also arise because a particular definition is forced to be monomorphic (unless you specifically say otherwise), which forces a single type to be chosen instead of retaining the polymorphism. I suspect that might be your problem, but I can't tell without the context you've removed.
To illustrate the latter, the following definition:
foo = print
...with no type signature, causes an error like this:
Test.hs:12:7:
Ambiguous type variable `a0' in the constraint:
(Show a0) arising from a use of `print'
Possible cause: the monomorphism restriction applied to the following:
foo :: a0 -> IO () (bound at Test.hs:12:1)
Probable fix: give these definition(s) an explicit type signature
or use -XNoMonomorphismRestriction
In the expression: print
In an equation for `foo': foo = print

Resources