Re: [Haskell-beginners] Compiler can't deduce Bool as instance of ToField

Bryan Vicknair: postgresql-simple declares Bool as an instance of the ToField class. The compiler can't deduce that given this simple code however:
import Database.PostgreSQL.Simple.ToField (ToField(..))
foo :: (ToField a) => a foo = True
It fails with this error:
Db.hs:64:7: Could not deduce (a ~ Bool) from the context (ToField a) bound by the type signature for foo :: ToField a => a at Db.hs:63:8-23 `a' is a rigid type variable bound by the type signature for foo :: ToField a => a at Db.hs:63:8 In the expression: True In an equation for `foo': foo = True Failed, modules loaded: none.
What am I missing?
Oliver Charles You have declared that foo is *any* type that has a ToField instance, allowing the caller of foo to determine the type at their will. However, your implementation of foo is more specific and requires a is actually Bool and nothing else. On 14 Aug 2013 10:24, "Bryan Vicknair"
wrote:
I see. I was confused, because the following works: bar :: (Num a) => a bar = 5 I guess it is because the literal '5' could be an Int or a Float, and the type system doesn't know. When I saw that the following does not work...:: bar :: (Show a) => a bar = False ...it made a bit more sense. It seems that if a literal can be considered part of a typeclass in more than one way, you can declare that literal to be of that typeclass. However, if there is only one way for a literal to belong to a typeclass, then you can't. Are there other literals (besides (Num a) => [a]) that don't have a concrete type like literal numbers? If I understand correctly, -XOverloadedStrings turns all literal strings into IsString instead of [Char], so that seems to be another case. I don't have a need for this, but now I'm curious: is there a way to declare that all literal numbers in a module are of a certain concrete type? Something like -XAllNumbersAreInt8?

On 15 Aug 2013, at 19:49, Bryan Vicknair
Bryan Vicknair: postgresql-simple declares Bool as an instance of the ToField class. The compiler can't deduce that given this simple code however:
import Database.PostgreSQL.Simple.ToField (ToField(..))
foo :: (ToField a) => a foo = True
It fails with this error:
Db.hs:64:7: Could not deduce (a ~ Bool) from the context (ToField a) bound by the type signature for foo :: ToField a => a at Db.hs:63:8-23 `a' is a rigid type variable bound by the type signature for foo :: ToField a => a at Db.hs:63:8 In the expression: True In an equation for `foo': foo = True Failed, modules loaded: none.
What am I missing?
Oliver Charles You have declared that foo is *any* type that has a ToField instance, allowing the caller of foo to determine the type at their will. However, your implementation of foo is more specific and requires a is actually Bool and nothing else. On 14 Aug 2013 10:24, "Bryan Vicknair"
wrote: I see. I was confused, because the following works:
bar :: (Num a) => a bar = 5
I guess it is because the literal '5' could be an Int or a Float, and the type system doesn't know.
When I saw that the following does not work...::
bar :: (Show a) => a bar = False
...it made a bit more sense. It seems that if a literal can be considered part of a typeclass in more than one way, you can declare that literal to be of that typeclass. However, if there is only one way for a literal to belong to a typeclass, then you can't.
That’s not it here. What you’re saying in the first case is “no matter what numeric type you want, I can provide it”. This is true, because the compiler can decide that 5 can indeed be any numeric type. In the latter case you make the promise “no matter what type you want, as long as you can show it, I can provide it”, but it’s false. I can say “well okay, give me an Int” and your function can not provide it to me, despite telling me in its type signature that it can. Tom Davie

The type of 5: Prelude> :t 5 5 :: Num a => a That's why it works. The literal's type uses the type class. Other fun stuff: Prelude> :t "asdf" "asdf" :: [Char] Prelude> :set -XOverloadedStrings Prelude> :t "asdf" "asdf" :: Data.String.IsString a => a

On Fri, Aug 16, 2013 at 12:49 AM, Bryan Vicknair
I guess it is because the literal '5' could be an Int or a Float, and the type system doesn't know.
The literal '5' is *known* to be of the *polymorphic* type (Num a => a). Ints and Floats are monomorphic instances of this polymorphic type. See http://www.haskell.org/onlinereport/basic.html#numeric-literals
When I saw that the following does not work...::
bar :: (Show a) => a bar = False
...it made a bit more sense. It seems that if a literal can be considered part of a typeclass in more than one way, you can declare that literal to be of that typeclass. However, if there is only one way for a literal to belong to a typeclass, then you can't.
I don't have a need for this, but now I'm curious: is there a way to declare
The part "if a literal can be considered part of a typeclass in more than one way" isn't how you want to think about them (see link). Good attempt though. that all literal numbers in a module are of a certain concrete type? Something like -XAllNumbersAreInt8? You enforce monomorphism by specifying type signatures where appropriate. In some cases, a light touch is all that's needed because type inference does the rest. -- Kim-Ee
participants (4)
-
Bryan Vicknair
-
David McBride
-
Kim-Ee Yeoh
-
Tom Davie