Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

types

haskell

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)
like image 840
Innocenzo Avatar asked Oct 27 '21 20:10

Innocenzo


People also ask

Can char have numbers?

The CHAR data type stores any string of letters, numbers, and symbols.

Can char accept numbers C++?

A signed char can hold a number between -128 and 127. An unsigned char can hold a number between 0 and 255.

How do you check if a char is a number?

We can check whether the given character in a string is a number/letter by using isDigit() method of Character class. The isDigit() method is a static method and determines if the specified character is a digit.

How do you check if a char is a number in C#?

In C#, we can use the IsDigit() method to check if a character is numeric or a digit. The IsDigit() method can be used on a single character or on a string. In the case of a string, we have to specify the index position of the character in the string.


2 Answers

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.

like image 139
chepner Avatar answered Nov 15 '22 07:11

chepner


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.

like image 34
Willem Van Onsem Avatar answered Nov 15 '22 08:11

Willem Van Onsem