Search code examples
haskelltypesalgebraic-data-types

Invalid data type


The following code is invalid:

data A = Int | [Int] | (Int, Int)

Why is it ok to use the concrete type Int as part of a data type definition, but not the concrete type [Int] or (Int, Int)?


Solution

  • Why is it ok to use the concrete type Int as part of a data type definition (..)

    It is not OK.

    What you here have written is the definition of a data type A that has a constructor named Int. This has nothing to do with the data type Int, it is simply a coincidence that the name of the constructor is the same as the name of a type, but that is not a problem for the Haskell compiler, since Haskell has a clear distinction between types and constructor names.

    You can not use [Int] however, since [Int] is not an identifier (it starts with an open square bracket), nor is it an operator (that can only use symbols). So Haskell does not really knows how to deal with this and errors on this input.

    If you want to define a datatype that can take an Int value, you need to add it as a parameter. You can also define constructors for your [Int] and (Int, Int) parameters. For instance:

    data A = Int Int | Ints [Int] | Int2 (Int,Int)

    So here there are three constructors: Int, Ints, and Int2. And the first constructor takes an Int as parameter, the second one an [Int], and the last one an (Int, Int).

    That being said, this will probably result into a lot of confusion, so it is better to use constructor names that cause less confusion, for instance:

    data A = A Int | As [Int] | A2 (Int,Int)

    Note that the A of data A can be used in the signature of the functions, whereas the constructors (in boldcase) are used as values (so in the implementation of the function, that is the pattern matching in the head of the clauses, and in order to construct a value in the body of the clauses).