Principles of Programming Languagesppl172/wiki.files/class/... · Mutable data types can be modeled...

Post on 10-Oct-2020

2 views 0 download

Transcript of Principles of Programming Languagesppl172/wiki.files/class/... · Mutable data types can be modeled...

Collaboration and ManagementDana Fisman

1

Principles of Programming Languages

www.cs.bgu.ac.il/~ppl172

Lesson 5 - Data Types and

Operations on Data

2

Types - what we already know

Types define sets of values There are atomic and compound types

The programmer can define data types and annotate its code in order to reflect the intended meaning of variables and functions

A process called type checking can analyze the program to verify there are no type discrepancies

3

Types - third important role

Type definitions help the programmer structure the code that operates on complex data values in a way that reflects the structure of the data type.

Knowing the structure of a data type helps the programmer write correct functions that operate over values of this type.

And vice versa, the decision on how to design the data type is driven by the operations that need to be preformed on them, and the desire to make them uniform.

4

Types - third important role

We will illustrate this point through four examples:

Homogeneous array types and the sequence interface (map, filter, reduce, …) Disjoint types and Disjoint Unions to enable uniform functional interfaces Modeling trees Mutable data types in FP

5

Homogeneous Array Types and the Sequence Interface

Array values can be ohomogeneous (all items are of the same types) or oheterogeneous (not all items are of the same type)

The natural way to process homogenous arrays is using the sequence interface (the set of higher order functions which can be applied to them) o map o filter o reduce o and others (every, some, find, etc.)

6

Homogeneous Array Types and the Sequence Interface

7

Homogeneous Array Types and the Sequence Interface

Can we always apply map(f,array) on array?

When can we?

When o the array is of type <SomeType>[] and o f is of type <SomeType> => <PossiblyAnotherType>

8

Homogeneous Array Types and the Sequence Interface

When can we apply filter (p?,array) on array?

When o the array is of type <SomeType>[] and o p? is of type <SomeType> => boolean

When can we apply reduce (f, init, array) on array?

When o the array is of type <SomeType>[] and o f is of type <PossiblyOtherType>,<SomeType> => <PossiblyOtherType> o init is of type <PossiblyOtherType>

Heterogenous

arrays do not lend

themselves to map

etc.

9

Creating new data types We have seen various ways to create new data types:

Array types Map types Generic types

We have discussed the set relations among created data types. Can we create new data types simply using set relations?

Cartesian product? Union? Intersection?

10

Typescript Union and Intersection

We can we create new data types simply using typescript’s union and intersection

type NoS = number | string; type SoB = string | boolean; type S = NoS & SoB;

11

Structural vs. Nominal Subtyping

Under nominal typing (as in Java)

these two types are disjoint.

Compiles ok !

Under structural typing (as in Javascript)

these two types are equivalent.

But sometimes

we do want to distinguish

these!

12

Disjoint Types

Does not compile as

desired

Compilation error: Type 'Person' is not assignable to type ‘Variable'.

Types of property 'tag' are incompatible.

The addition of field tag caused the two types to be disjoint!

13

Disjoint Union

By combining type union operator | and a mutual field (tag) with distinct values we can obtain disjoint types.

Mathematical definition:

14

Disjoint Union

15

Disjoint Union

disjoint union together with the corresponding switch

construct achieves an effect similar to sub-classes with

virtual classes in OOP

It allows the function to dispatch to different

computations based on the type of the actual value received as a parameter.

16

Modeling Trees with Types

bt = {“root”:2, "left":{"root":3,"left":{"root":4}}, "right":{"root":5,"right":{"root":6}}}

traverseDFS(bt);

==>2 3 4 5 6

The function processing the data type is structured in

the same way Different fields have different

assurance on their

existence

Using type analysis we can verify we are safe and exhaustive

17

Modeling Trees with Types

squareTree(bt2); ==> { root: 4, left: { root: 9, left: { root: 16 } }, right: { root: 25, right: { root: 36 } } }

Being

exhaustive

resulted in

lots of

repeated code

18

Modeling Trees with Types By relaxing type checking and accepting undefined as a return value we can make the code shorter and more readable:

19

Modeling Trees with Types

squareTree2(bt)

{ root: 4, left: { root: 9, left: { root: 16, left: undefined, right: undefined }, right: undefined }, right: { root: 25, left: undefined, right: { root: 36, left: undefined, right: undefined } } }

Output:

20

Modeling Trees with Types Let us reflect on this version:

The expected values of type BinTree were extended to include undefined

We explicitly test for undefined as the first base case in the recursive function.

The recursive calls are now simplified as we can avoid the recursive calls with a value undefined

The return value has values marked explicitly as undefined - these are semantically equivalent to absent values - but in the syntax of the object, they still appear.

21

Modeling Trees with Types How can we eliminate the undefined in the output? Using JSON.stringify()

The two version correspond to different styles

undefined may complicate analysis

but is hard to avoid

22

Mutable Data Types in FP

Suppose we want to implement in FP a stack, which is mutable by nature?

push(x)

pop()

empty() Query. Does not mutate.

Mutate. And return a value.

23

Mutable Data Types in FP Let us separate to pure queries and pure mutators

push(x)

pop()

peek()

empty()

Mutators

Queries

This definition is still inherently procedural

The result maybe that even queries are

not deterministic

Can return different values on same calls

24

Mutable Data Types in FP Non-Functional Implementation

Relies on arrays being mutable

Generic

Queries. No mutations.

Constructor

Mutators

25

Mutable Data Types in FP Can a non-deterministic behavior of queries really occur?

Peek(s) on the same value s, returns different results

26

Mutable Data Types in FP Functional Implementation (not efficient)

Generic

Queries. No mutations.

Constructor

Return new copy

Cloning utility (shallow)

27

Mutable Data Types in FP Does it provides a deterministic behavior?

Yes! This implementation

is safe

But inefficient!

Using this implementation requires a change from the

client side: the interface

has a changed!

28

Mutable Data Types in FP What is the remedy?

Use efficient immutable libraries such as immutable-js by Facebook

29

Mutable Data Types in FP The immutablle-js library works well with JSON So we can e.g. construct a Stack for a string

30

Summary

Type definitions help the programmer structure the code that operates on complex values in a way that reflects the structure of the data type.

Programmers design and name types for sets of values that will be processed by the same set of functions.

Homogeneous array types encourage the programmer to consume them using the sequence interface (map, filter, reduce)

31

Summary Recursive types are processed by recursive functions othe recursive functions inspect the values according to the type definition

oand can determine the base case and the inductive case.

Mutable data types can be modeled in a Functional Programming style by making sure commands are written as constructors which return a new version of the values (instead of mutating an existing value).

Disjoint types and Disjoint Unions enable the definition of uniform functional interfaces over types of values that are not structurally similar.