Data declaration without a data constructor. Can it be created? Why does it compile?

While reading one of my Haskell books, I came across a suggestion:

Data declarations always create a new type of constructor, but they may or may not create new data constructors.

It was strange to be able to declare a data type without a data constructor, because it seems that then you can never instantiate the type. So I tried it. The following data declaration compiles without errors.

data B = String

      

How do I create an instance of this type? Is it possible? I cannot find a way.

I thought that a data constructor with a name that matches the type constructor would be generated automatically, but that doesn't look like the error shown by trying to use B

as a scoped data constructor.

Prelude> data B = String deriving Show
Prelude> B

<interactive>:129:1: error: Data constructor not in scope: B

      

Why is this data declaration allowed to compile if the type can never be created? Is this allowed solely for some formal reason, despite the fact that it has no known practical application?


I also wonder if my book statement on non-constructor data types can refer to types declared with type

or newtype

rather than data

.

  • In the case, type

    type synonyms do not explicitly use these constructors, as shown below.

    Prelude> type B = String
    Prelude>
    
          

    Type synonyms such as this can be created by the constructors of the type they are set to. But I'm not sure if this is what the book is referring to as type synonyms, it doesn't seem to declare a new data type as much as just defining a new alias for an existing type.

  • In case it newtype

    appears that types without data, constructors cannot be created, as shown by the following error.

    Prelude> newtype B = String
    
    <interactive>:132:13: error:
        β€’ The constructor of a newtype must have exactly one field
            but β€˜String’ has none
        β€’ In the definition of data constructor β€˜String’
          In the newtype declaration for β€˜B’
    
          

type

and newtype

it doesn't seem to be relevant to what the book is talking about, which brings me back to my original question: why is it possible to declare a type using data

without a data constructor?

+3


source to share


1 answer


How do I create an instance of this type?

The statement from your book is correct, but your example is not. data B = String

defines a type constructor B

and a data constructor String

, both with no arguments. Note that the String

one you are defining is in the value namespace, therefore different from the normal type constructor String

.

ghci> data B = String
ghci> x = String
ghci> :t x
x :: B

      

However, here is an example of defining data without data constructors (so it cannot be created).

ghci> data B

      

Now I have a new type constructor B

, but no data constructors to create type values B

. In fact, this datatype is declared in Haskell base

: it's called Void

:

ghci> import Data.Void
ghci> :i Void
data Void   -- Defined in β€˜Data.Void’

      

Why is this data declaration allowed to compile if the type can never be created?

The ability to have uninhabited types comes in handy in several places. The examples I can think of now are mostly passed by a type such as a type parameter to another type constructor. Another practical use case is in streaming libraries such as conduit

.



There is a type constructor ConduitM i o m r

, where: i

- the type of the elements of the input stream, the o

type of the elements of the output stream, the m

monad in which the actions are performed r

- the final result obtained at the end.

He then defines Sink

as

type Sink i m r = ConduitM i Void m r

      

since a Sink

should never output any values. Void

is a compile-time guarantee that Sink

it cannot output any (non-bottom) values.

As Identity

, Void

mostly useful in combination with other abstractions.

... type synonyms do not explicitly use data constructors

Yes, but they don't define type constructors either. Synonyms are just a superficial renaming of convenience. Nothing new is defined under the hood.

In the case of the new type, it seems that types without data constructors cannot be created, as shown by the following error.

I suggest you see what for newtype

. The whole point newtype

is to provide a zero cost wrapper around the existing type. This means that you have one and exactly one constructor that takes one and only one argument (the wrapped value). At compile time, the wrapping and reversal operations become NOPs.

+8


source







All Articles