• Tidak ada hasil yang ditemukan

(Algebraic) Data Types

N/A
N/A
Protected

Academic year: 2025

Membagikan "(Algebraic) Data Types"

Copied!
6
0
0

Teks penuh

(1)

(Algebraic) Data Types

Type-safe abstractions

Defining multi-field records

data StudentT

=

Student

String Int

type name being

defined keyword

constructor (or wrapper) definition

field types / values in this wrapper

s1, s2 :: StudentT s1 = Student "Joe" 20 s2 = Student "Mary" 21

getName:: StudentT -> String getName (Student nm _) = nm

The type name can (only) be used in our type signatures. It always begins with capital letter.

The constructors(also capitalized) are used in

Patterns, for choosing the function leg / unwrapping the fields,

Expressions, for creating wrapped values of the given type.

Why is it called an algebraic data type?

An algebraprovides a way to combine simple elements (e.g. identifiers, constants) into more complex expressions, using operators.

An algebraicdata type provides mechanisms for assembling simple primitive types (e.g. Int, Char) into more complex multi-field or variant types.

Multi-case types

(Pascal variants, C calls them union types)

data ShapeT

= Circle Double

| Triangle Double Double Double

| Rectangle Double Double area :: ShapeT -> Double area (Circle r) = pi * r^2 area (Rectangle h w) = h * w area (Triangle a b c) = b * th / 2.0

where th = ???

(2)

The type QualityStreetSweetis a union of sixteen variants. Variants are identified by unique constructors / wrappers, which encapsulate their data.

Was this possibly the inspiration for Haskell’s type system?

Multi-case types – another example

data ColourT =

Red

| Green

| RGB Int Int Int

| GreyScale Int

| HSV Int Int Int toRGB:: ColourT -> ColourT toRGB Red = RGB 255 0 0 toRGB Green = RGB 0 255 0

toRGB (GreyScale v) = RGB v v v toRGB (HSV h s v) = … toRGB c = c -- catchall

A type that permits multiple ways to represent a colour.

A function to switch between representations.

enums fit nicely into this …

data DayT =

Sun| Mon| Tue| Wed| Thu| Fri| Sat data Bool = False| True

enums are just degenerate multi-case variant types without any "field data" – empty wrappers that don’t contain any chocolates.

That is why Falseand Wedare sometimes called constructorsrather than constants.

Are types like DayT and Bool members of classes Eq, Ord, Show , and Enum?

Not unless we provide instancedefinitions, and write all the functions that the class demands.

The prelude does this for Bool.

Main> [Sun .. Sat]

ERROR - Cannot infer instance

*** Instance : Enum DayT

*** Expression : enumFromTo Sun Sat Main> Tue < Fri

ERROR - Cannot infer instance

*** Instance : Ord DayT

*** Expression : Tue < Fri

The hard way out:

Implement the interfaces …

instance Enum DayT where toEnum 0 = Sun toEnum 1 = Mon toEnum 2 = Tue toEnum 3 = Wed toEnum 4 = Thu toEnum 5 = Fri toEnum 6 = Sat fromEnum Sun = 0 fromEnum Mon = 1

fromEnum Sat = 6

(3)

The hard way out:

Implement the interfaces …

instance Eq DayT where

(==) x y = (fromEnum x) == (fromEnum y) instance Ord DayT where

(<) x y = (fromEnum x) < (fromEnum y)

Haskell to the rescue …

As part of our data declaration, we can tell the compiler to derive what it thinks are the

"obvious" member functions needed for Class instances.

data DayT =

Sun| Mon| Tue| Wed| Thu| Fri| Sat deriving (Eq, Ord, Show, Enum)

Main> Tue < Fri True

Main> [Sun .. Sat]

[Sun, Mon, Tue, Wed, Thu, Fri, Sat]

Now it works …

The Hugs interpreter has a setting (u+), (default on), to automatically use show(from class Show) to display results. So it is a Good Idea to either derive or implement Show.

Abstract Data Types (ADTs)

data IntSetT = IntSet [Int]

union, intersection ::

IntSetT -> IntSetT -> IntSetT

We can exposethe type name and function signatures from a Haskell module, but we can hidethe implementation and representation details (including the wrapper names) from clients. i.e. we can build secure ADTs.

Hide this

union, intersection :: Ord a =>

SetT a -> SetT a -> SetT a Next, we add polymorphism…

Check yourself: can you explain the different roles of SetTand Set?

data Ord a => SetT a = Set [a]

We can keep the constructor(s) hidden inside the module …

t1 = list2Set ["abby", "joe", "bill"]

t2 = list2Set ["bill", "mary"]

t3 = intersection t1 t2 union, intersection::

Ord a => SetT a -> SetT a -> SetT a list2Set :: (Ord a) => [a] -> SetT a

This is an ADT – the client has no access to the internal representation. Usage:

(4)

Within the implementation, we use the wrappers / constructor(s) in our function bodies and patterns.

union:: Ord a => SetT a -> SetT a -> SetT a union (Set xs) (Set ys) =

Set (rawUnion xs ys) where

rawUnion::(Ord a)=>[a]->[a]->[a]

rawUnion … … = …

In the first line the bluepatterns "unwrap" the

encapsulated raw data, we operate locally on the lists, and the red Setconstructor re-wraps the result.

Exercise: How would you create a data structure to represent a binary tree?

If we can't do this yet, what do we still need to add to Haskell's type system?

At last, we get to define our own recursive data types ☺

In English, how would you describe a binary tree that holds a value at each node?

"A binary tree is either empty, or it is a node with a value, and a left subtree and a right subtree. Each subtree is a tree."

data TreeT a

= Empty

| Node

(TreeT a)

a (TreeT a) Beautiful, clever Haskell lets us express our intent exactly, with polymorphism too:

deriving Show

t1 = Node

(Node Empty "Haskell" Empty)

"is"

(Node(Node Empty "really" Empty)

"quite"

(Node Empty "amazing" Empty)) is

Haskell quite

really amazing t1

is

Haskell quite

really amazing t1

mkLeaf x = Node Emptyx Empty t1 = Node (mkLeaf "Haskell")

"is"

(Node(mkLeaf "really")

"quite"

(mkLeaf "amazing")) t2 = Node (mkLeaf 1) 2 (mkLeaf 3)

2

1 3 t2

(5)

Tree Exercises

Write a function to sum all the elements in a tree of Int.

Generalize this to work for any kind of number.

sumT :: (Num a) => TreeT a -> a

sumT

Empty

= 0 sumT (Node l n r) =

sumT l + n + sumT r

Write a function to produce the mirror- image of a tree.

is

Haskell quite

really amazing

is

Haskell quite

really

amazing

A binary tree in which every node has exactly two or zero children is a strict binary tree, sometimes called a fulltree. Write a predicate to determine whether a tree is strict.

is Haskell quite

really amazing

2

1

3

Write flatten, which takes a tree and produces a list of values from the tree, (in-order traversal, i.e. LNR order).

1 2 5

4 3

[3, 2, 4, 1, 5]

flatten :: TreeT a -> [a]

Notice how the "form of the program"

closely mirrors the "form of the data".

flatten Empty = [ ] flatten (Node l v r) =

flatten l ++ [v] ++ flatten r

(6)

Write a function that doubles every element in a binary tree of numbers.

Write a function which returns the height of a binary tree.

Write a function which counts the number of non-leaf nodes in a binary tree.

A binary search tree(BST) has special ordering properties – what are they?

Write a function which inserts a new element into a BST.

Summary

The type system is type-safe.

It supports polymorphism.

Allows one to express enumerations, variants, and recursive typeselegantly.

Plays together particularly well with Haskell's pattern matchingand multi-leg definitions.

Referensi

Dokumen terkait

The integer abstract data type group consists of four abstract data types used to reserve memory to store whole numbers : byte , short , int , and long , as described in

Scalar adalah nama lain dari data numeric, Dalam MATLAB data scalar dapat dimanipulasikan dengan menggunakan beberapa fungsi, seperti type string sebelumnya.. MATLAB menangani

To each Range data type (CategoryRange, CountRange,QuantityRange and TimeRange), add an alternate encoding where each of the elements of the range will have an explicit property

In the MapReduce world, using JSON data as input data eliminates the need for custom writables because the JSON string can be serialized in the Hadoop Text type. This process can be

!"#$!%" &'*+,-./,*+010+20 " struct qq { int data[Max_no]; enum que queue_state; }; struct qq FIFO_Q; ตัวอยางขางตน แสดงการจํ าลองโครงสรางของ queue ดวย structure โดยตัว queue