I don't understand why when I look at the type for example of:
a = (1, 2)
I get a :: (Num a, Num b) => (a, b)
instead, if I look at the type of:
b = ('a', 'b')
I get b :: (Char, Char)
and not something like:
b :: (Char a, Char b) => (a, b)
?
Thanks in advance!
CodePudding user response:
Num
is a typeclass, it is a set of types, this looks a bit similar to what an interface is in Java/C#/... The types that are members of the Num
typeclass need to implement a certain set of functions, like in Java where types that implement the interface should implement certain methods. A Char
on the other hand is a type, not a typeclass.
If you write an integer literal, it can be of any type that is a member of the Num
typeclass, since that typeclass has a function fromInteger :: Num a => Integer -> a
that is then called to convert the integer literal to that number type.
If you write a char literal like 'a'
on the other hand, then the only type to which this can be resolved is a Char
.
For string literals, you can use the OverloadedStrings
extension, in that case a string literal can take any type that is a member of the IsString
typeclass.
CodePudding user response:
Haskell has two types of literals: monomorphic and polymorphic. (Though it might be more accurate to say, literals can evaluate to values of monomorphic or polymorphic types.)
'c'
is an example of a monomorphic literal; it is a value of a single type, namely Char
.
> :t 'c'
'c' :: Char
1
, on the other hand, is a polymorphic literal. It can be a value of any type that has a Num
instance.
> :t 1
1 :: Num p => p
> :t 1 :: Int
1 :: Int :: Int
> > :t 1 :: Char
<interactive>:1:1: error:
• No instance for (Num Char) arising from the literal ‘1’
• In the expression: 1 :: Char
Other polymorphic literals include
Floating-point literals
> :t 3.4 3.4 :: Fractional p => p
String literals, when the
OverloadedStrings
extension is enabled.> :t "foo" "foo" :: [Char] > :set -XOverloadedStrings > :t "foo" "foo" :: Data.String.IsString p => p
List literals, when the
OverloadedLists
extension is enabled.> :t ['a', 'b'] ['a', 'b'] :: [Char] > :set -XOverloadedLists > :t ['a', 'b'] ['a', 'b'] :: (GHC.Exts.IsList l, GHC.Exts.Item l ~ Char) => l
Data constructors like
Nothing
(if you want to think of nullary constructors as literals)> :t Nothing Nothing :: Maybe a
Nothing
, for example, can be a value of typeMaybe Int
,Maybe Char
, etc.