blue-sky
blue-sky

Reputation: 53826

What is Ord type?

Is every class not a type in Haskell :

Prelude> :t max
max :: Ord a => a -> a -> a
Prelude> :t Ord

<interactive>:1:1: Not in scope: data constructor ‘Ord’
Prelude> 

Why does this not print Ord type signature ?

Upvotes: 8

Views: 12902

Answers (4)

luqui
luqui

Reputation: 60463

Ord is not a type, but a typeclass. It does not have a type, but a kind:

Prelude> :k Ord
Ord :: * -> Constraint

Typeclasses are one of the wonderful things about Haskell. Check 'em out :-)

Upvotes: 3

Ben
Ben

Reputation: 71485

Okay, there's a couple of things going on here.

First when you write :t Ord you're looking for something called Ord in the value namespace; specifically it would have to be a constructor, since the name starts with a capital letter.

Haskell keeps types and values completely separate; there is no relationship between the name of a type and the names of a type's constructors. Often when there's only one constructor, people will use the same name as the type. An example being data Foo = Foo Int. This declares two new named entities: the type Foo and the constructor Foo :: Int -> Foo.

It's not really a good idea to think of it as just making a type Foo that can be used both in type expressions and to construct Foos. Because also common are declarations like data Maybe a = Nothing | Just a. Here there are 2 different constructors for Maybe a, and Maybe isn't a name of anything at all at the value level.

So just because you've seen Ord in a type expression doesn't mean that there is a name Ord at the value level for you to ask the type of with :t. Even if there were, it wouldn't necessarily be related top the type-level name Ord.

The second point that needs clarifying is that no, classes are not in fact types. A class is a set of types (which all support the interface defined in the class), but it is not a type itself.

In vanilla Haskell type classes are just "extra" things. You can declare them with a class declaration, instantiate them with an instance declaration, and use them in special syntax attached to types (the stuff left of the => arrow) as constraints on type variables. But they don't really interact with the rest of the language, and you cannot use them in the main part of a type signature (the stuff right of the `=> arrow).

However, with the ConstraintKinds extension on, type classes do become ordinary things that exist in the type namespace, just like Maybe. They are still not types in the sense that there can never be any values that have them as types, so you can't use Ord or Ord Int as an argument or return type in a function, or have a [Ord a] or anything like that.

In that they are a bit like type constructors like Maybe. Maybe is a name bound in the type namespace, but it is not a type as such; there are no values whose type is just Maybe, but Maybe can be used as part of an expression defining a type, as in Maybe Int.

If you're not familiar with kinds, probably ignore everything I've said from ConstraintKinds onwards; you'll probably learn about kinds eventually, but they're not a feature you need to know much about as a beginner. If you are, however, what ConstraintKinds does is make a special kind Constraint and have type class constraints (left of the => arrow) just be ordinary type-level things of kind Constraint instead of special purpose syntax. This means that Ord is a type-level thing, and we can ask it's kind with the :k command in GHCI:

Prelude> :k Ord
* -> Constraint

Which makes sense; max had type Ord a => a -> a -> a, so Ord a must have kind Constraint. If Ord can be applied to an ordinary type to yield a constraint, it must have kind * -> Constraint.

Upvotes: 13

Alec
Alec

Reputation: 32309

Not quite. You can impose type constraints, so Ord a => a is a type, but Ord a isn't. Ord a => a means "any type a with the constraint that it is an instance of Ord".

The error is because :t expects an expression. When GHCi tries to interpret Ord as an expression, the closest it can get to is a data constructor, since these are the only functions in Haskell that can start with capital letters.

Upvotes: 1

MaxGabriel
MaxGabriel

Reputation: 7707

Ord isn't a type; it's a typeclass. Typeclasses allow you to associate supported operations with a given type (somewhat similar to interfaces in Java or protocols in Objective-C). A type (e.g. Int) being an "instance" of a typeclass (e.g. Ord) means that the type supports the functions of the Ord typeclass (e.g. compare, <, > etc.).

You can get most info about a typeclass using :i in ghci, which shows you the functions associated with the typeclass and which types are instances of it:

ghci > :i Ord
class Eq a => Ord a where
  compare :: a -> a -> Ordering
  (<) :: a -> a -> Bool
  (>=) :: a -> a -> Bool
  (>) :: a -> a -> Bool
  (<=) :: a -> a -> Bool
  max :: a -> a -> a
  min :: a -> a -> a
    -- Defined in ‘GHC.Classes’
instance Ord a => Ord (Maybe a) -- Defined in ‘Data.Maybe’
instance (Ord a, Ord b) => Ord (Either a b)
  -- Defined in ‘Data.Either’
instance Ord Integer -- Defined in ‘integer-gmp:GHC.Integer.Type’
instance Ord a => Ord [a] -- Defined in ‘GHC.Classes’
...

Upvotes: 8

Related Questions