Home > OS >  How to use the syntax and access values in custom data types in Haskell?
How to use the syntax and access values in custom data types in Haskell?

Time:12-11

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 as 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.

  • Related