I am trying to understand how the following are used:
data Maybe a = Nothing | Just a
data Either a b = Left a | Right b
From my understanding these are parameterized algebraic data types. Coming from an OO background, I would now like to create an instance of these objects. If I do something like:
x = Maybe 10
Is that now a subclass/sub-algebraic-data-type, or wondering what that object is called. I would assume it is a type of some sort. If so, then I am wondering how to create an instance of x
. In OO land I would do:
myinstance = new x
This is where coming to Haskell gets me lost and I'm not sure where to search. A few questions to summarize:
x
is above. If Maybe
is a parameterized data type, then x is ~something~ type, not sure.x
.x
for Maybe, since we passed it 10. Wondering, if the instance value is 10 and has type Int.There is no such thing as Maybe 10
in Haskell. There is Maybe Int
, which is a type.
We create a value of a certain type, directly, as
x :: Maybe Int
x = Just 10
or
y :: Maybe Int
y = Nothing
Simple and direct.
edit: Maybe
is a type constructor. Just
and Nothing
are data constructors. By writing Maybe Int
we "create" a type. There can't be a definition z :: Maybe ; z = .....
.
This is known as "kind": the kind of Maybe
is * -> *
, while e.g. Int
's is *
and so is Maybe Int
's. Try :k
at GHCi prompt to see this:
~> :k Int
Int :: *
~> :k Maybe
Maybe :: * -> *
~> :k Maybe Int
Maybe Int :: *
Of course we don't actually create a new type when we write "Maybe Int
, it's just that Maybe
by itself is not a type of things yet (types of "things" have kind *
).
The definition for Maybe
is what creates the types Maybe a
, for any a
we might use. This is known as parametric polymorphism.
So in Haskell, we don't have objects (in the OOP sense). We have values and types.
What kind of object x is above. If Maybe is a parameterized data type, then x is ~something~ type, not sure.
You can not construct a Maybe 10
, you can for example construct a Just 10
. In case 10
is here an Int
(well technically it can be any numerical type, but let us ignore that for now), then you constructed a Maybe Int
.
Note that a
in Maybe a
, is one meta level higher: it works with types. Hence a
is a type parameter. It thus does not take as value 10
, but for example Int
.
What you can do however is define a type alias for Maybe Int
, for example:
type X = Maybe Int
Note that we here use type
as a type alias, not data
to construct a data type.
Types (and type aliasses) always start with an upper case, so we can not define a type x
, only a type X
. A type has no default constructor (which is typically the case in OO programming languages).
How to create an instance of x.
Haskell can derive the most generic type of an expression itself. We thus write an expression that has the type of Maybe Int
, so for example
Just 10
In case the type would be too generic (here it will be Num a => Maybe a
), we can give a hint to Haskell by using two consecutive colons (::
), for eample:
Just 10 :: Maybe Int
or since we already introduced the type alias X
:
Just 10 :: X
What is the instance of x for Maybe, since we passed it 10. Wondering, if the instance value is 10 and has type Int.
Welll as said before, types in Haskell have no default constructor. We here have two candidates: Just n
with n
an Int
(in case we use type X
), or Nothing
. So we pick one of the two:
Just 10 :: X
Nothing :: X
Since you can not change the state of an object anymore after you constructed it (i.e. all objects in Haskell are immutable), that means that it would be strange that a default constructor sets some initial data, and then later methods would change that object.
You can therefore see a data constructor (here Just
and Nothing
) as a labelled container that holds a group of parameters together in a container, and labels it with what constructor was used. So a graphical view of the objects would be:
+------+ +---------+
| Just | | Nothing |
+------+ +---------+
| o |
+---|--+
|
v
+----+
| 10 |
+----+
When you write an algebraic type definition as
data Maybe a = Nothing | Just a
the LHS is a type construction expression (it states that Maybe
has kind * -> *
), and the RHS is a disjunction of alternatives each one being a value constructor, so for type Maybe a
, Just
is an unary constructor that creates an object of this type, and Nothing
is the nullary one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With