Construct Value
This section explores the concepts of value, value constructor, type and kind in PureScript.
Intro
Value
A value
refers to a concrete runtime expression — something that the program evaluates, stores, or passes around. We can construct values by value/data constructor
(custom) and literals
(built-in). Value has a type
, and we can examine with :type
or :t
in REPL.
Type
Type
describes what kind of data something is. Type has a kind
, and we can use :kind
or :k
to examine in REPL. There is a special kind called Type which represents the kind of all types which have values, like Number and String.
Type constructor
Type constructor takes type argument and construct type.
data Maybe a = Nothing | Just a
Maybe a
: a typeMaybe
: a type constructor, which takes a type parameter, and creates a type (Maybe a)Just a
: a valueJust
: a value constructor, which takes a parameter, and create a value (Just a) of type Maybe a;
List is an example of a type constructor. Values do not have the type List directly, but rather List a for some type a. That is, List takes a type argument a and constructs a new type List a.
Note that just like function application, type constructors are applied to other types simply by juxtaposition: the type List Entry is, in fact, the type constructor List applied to the type Entry – it represents a list of entries. There are also kinds for type constructors. For example, the kind Type -> Type represents a function from types to types, just like List.
Value Constructor
Constructor
makes values of that type. A value constructor (also known as a data constructor) is a function that constructs a value of a data type. Value constructors are just functions that take the fields as parameters and return a value of some type (like Shape) as a result.
Examples
The following are examples for these concepts.
Some values
Expression | Is it a Value? | Type | Notes |
---|---|---|---|
7 | ✅ Yes | Int | A number literal |
"hello" | ✅ Yes | String | A string literal |
true | ✅ Yes | Boolean | A boolean literal |
Circle 0.0 0.0 5.0 | ✅ Yes | Shape | A value constructed using a data constructor |
Just 5 | ✅ Yes | Maybe Int | Value using a built-in algebraic data type |
add 1 2 | ✅ Yes | Int | Result of a function application |
\x -> x + 1 | ✅ Yes | Int -> Int | A function value (lambda expression) |
Some types and type definition
Thing | What it is | Kind | Why it's not a value |
---|---|---|---|
Int | A type | Type | Describes values like 7 , but isn’t a value |
Shape | A type name | Type | A category of values, not a value itself |
data Shape = ... | Type declaration | (not applicable) | Defines a type and its constructors, not a value |
add :: Int -> Int -> Int | Type annotation | (not applicable) | Describes the type of a value, not the value itself |
Value, Type and Constructor
Value | Type | Constructor? | Notes |
---|---|---|---|
7 | Int | ❌ None | Literal for a primitive type |
true | Boolean | ❌ None | Same |
Circle | Shape | ✅ Circle | User-defined data constructor |
Just 5 | Maybe | ✅ Just | Built-in algebraic data type |
Code example:
data Shape = Circle Number Number Number
| Rectangle Number Number Number Number
This defines a type named Shape
, and two data constructors.
Literal
In PureScript (and many programming languages), the term "literal" refers to syntax that allows you to directly write a value of a specific type in your code, without needing to construct it through functions or other runtime operations.
A string literal
is text written directly between double quotes ("..."):
-- A string literal representing the value "hello"
str :: String
str = "hello"
An array literal
is a list of values written between square brackets ([ ... ]):
-- An array literal with the values 1, 2, 3
arr :: Array Int
arr = [1, 2, 3]
Contrast with Non-Literal Constructs:
-- Non-literal (constructed at runtime):
dynamicArray = Array.cons 1 (Array.cons 2 (Array.cons 3 []))
dynamicString = String.fromCharArray ['h', 'e', 'l', 'l', 'o']
Why "Literal" Matters:
- Compile-Time Known: Literals are fixed values embedded in the source code.
- No Runtime Overhead: They don’t require functions like Array.from or new Object().
- Pattern Matching: Can be used directly in patterns:
Summary
Concept | Role | Example |
---|---|---|
Type | Category of values | Shape |
Constructor | Function to create values | Circle 1.0 1.0 5.0 |
Value | Actual instance of a type | myShape = Circle 1.0 1.0 5.0 |
Pattern match | Use constructors to handle data | case shape of Circle x y r -> ... |