Home > database >  Why do Chars not have a `Char a => a` similar to numbers (`Num a => a`)?
Why do Chars not have a `Char a => a` similar to numbers (`Num a => a`)?

Time:10-29

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)

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

  1. Floating-point literals

    > :t 3.4
    3.4 :: Fractional p => p
    
  2. String literals, when the OverloadedStrings extension is enabled.

     > :t "foo"
     "foo" :: [Char]
     > :set -XOverloadedStrings
     > :t "foo"
     "foo" :: Data.String.IsString p => p
    
  3. 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
    
  4. 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 type Maybe Int, Maybe Char, etc.

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:

The point of numerical literals being polymorphic is that you can use them in numerical expressions for wildly different number types.

Prelude> 1   10^12 :: Int
1000000000001
Prelude> pi   10^12 :: Double
1.0000000000031416e12
Prelude> 1/3   10^12 :: Rational
3000000000001 % 3
Prelude> sqrt (-1)   10^12 :: Data.Complex.Complex Double
1.0e12 :  1.0
Prelude> :m Text.LaTeX
Prelude Text.LaTeX> phi   10^12 :: LaTeX
TeXSeq (TeXComm "phi" []) (TeXSeq (TeXRaw " ") (TeXSeq (TeXRaw "10") (TeXSeq (TeXRaw "10") (TeXSeq (TeXRaw "10") (TeXSeq (TeXRaw "10") (TeXSeq (TeXRaw "10") (TeXSeq (TeXRaw "10") (TeXSeq (TeXRaw "10") (TeXSeq (TeXRaw "10") (TeXSeq (TeXRaw "10") (TeXSeq (TeXRaw "10") (TeXSeq (TeXRaw "10") (TeXRaw "10")))))))))))))

Mighty useful, because such different numerical types really are used in practice.

But I don't see much point in having something like this for characters, Char really is the only type that makes sense. (I suppose you could argue that having a Char8 type could sometimes be useful, but this is the Unicode age, a character outside of a string anyways occupies 64 bits, and low-level manipulations should probably be done with Word8 and not use character literals.)

By contrast, for strings it does make a lot of sense to support other types apart from the old [Char], that's why -XOverloadedStrings makes string literals polymorphic.

  • Related