I have a data type defined like:
data MyType a = MyType Weight [a]
and Weight is type Weight = Integer.
I don't exactly understand what is going on here. Is MyType
comprising of an integer or [a]
, or both?
In my case, I have gotten MyType (a,b)
, and I want to know, is this a list of (a,b)
, and if so, what syntax do I need to use in order to extract just the list of a
?
CodePudding user response:
MyType
is a type comprised by Int
and [a]
, so it has both. To extract the list from the type, you can use pattern matching:
getList :: MyType a -> [a]
getList (MyType _ a) = a
Alternatively, you can declare the type using record syntax:
data MyType a = MyType { getWeight :: Weight, getList :: [a] }
which automatically generates the unpacking functions, so that getList (MyType 2 [3,4]) == [3,4])
CodePudding user response:
As you say,
data MyType a = MkMyType Weight [a]
-------- -------- ------ ---
-- type data type of type of
-- constructor 1st field 2nd field
defines a data type. Notice that I made one small alteration, writing MkMyType
to the right of the =
to differentiate it from the MyType
on the left.
Now, for any specific a
, MyType a
is a data type -- it is a type of stuff that can appear on the right hand side of a definition.
MkMyType
though (of type Weight -> [a] -> MyType a
) is a data constructor. Applied to a Weight
-type value, and a [a]
-type value, it creates a value of type MyType a
, which indeed holds on to two values at the same time -- a Weight
-type value, and a [a]
-type value, which were given to it at the time of its creation.
How this value is represented in the computer memory is not important. What is important is that we can pattern match on it like e.g.
foo :: MyType a -> (Weigth, [a])
foo (MkMyType w as) = (w, as)
--------------------
-- pattern 1st 2nd
-- field field
Notice that in the value MkMyType w as
we have the value w
of type Weight
(we write: w :: Weight
) and we also have as
of type [a]
-- with the same a
as appears in the overall type.
Thus we can also define
bar :: MyType (a,b) -> (Weigth, [(b,a)])
bar (MkMyType w abs) = (w, [(b,a) | (a,b) <- abs])
and again, here we have abs :: [(a,b)]
because the argument value's type is MyType (a,b)
-- with the same a
and b
.
So if you only want to get the list of a
s from the abs
, you can write
baz :: MyType (a,b) -> [a]
baz (MkMyType _ abs) = takeFirsts abs
and here you need to implement
takeFirsts :: [(a,b)] -> [a]
takeFirsts abs = ...
which I leave for you to complete, as an exercise.