O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Type Systems

183 visualizações

Publicada em

What comes to your mind when you hear the word "type"? Do you think of an integer or string? Do you think of an object type from your favorite OOP language? Do you think about never ending religious debates regarding static vs dynamic types? Do you realize that these things hardly scratch the surface of what it means to be a "type"? Be prepared to understand types on a whole new level.

In this talk, we will explore type systems. What is a type system? Why are type systems important? How have type systems been influenced by functional programming, category theory, and type theory?

We will talk about variance, polymorphisms, higher-kinded types, existential types, algebraic data types, and type classes. We will scratch the surface of type theory and learn how logic systems have influenced programming language design.

This talk will be approachable to a wide audience and previous knowledge of type theory is not needed.

Publicada em: Software
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

Type Systems

  1. 1. Type Systems Jordan Parmer @ProfParmer
  2. 2. What is a Type System? “A set of rules that assigns a property called a ‘type’ to the various constructs of a computer program such as variables, expressions, functions, or modules. These types formalize and enforce the otherwise implicit categories the programmer users for algebraic data types, data structures, or other components.” -Wikipedia
  3. 3. What is a Type System? “A type system is a tractable syntactic method for proving the absence of certain program behaviors by classifying phrases according to the kinds of values they compute.” - Benjamin Pierce in Types and Programming Languages
  4. 4. What is a Type System? “Intuitively speaking, you want your type system to induce a system of logic that is consistent, i.e. that doesn't allow false theorems to be proven. The more inconsistent the system of logic induced by the type system is, the less useful the type system is as a proof of correctness of the code.” - Jorg Mittag
  5. 5. What are the goals of a type system?
  6. 6. Type System Goals ◦ Check for bad program behavior ◦ Early detection of program errors ◦ Enable abstractions ◦ Protect integrity of user defined abstractions ◦ Documentation ▫ Easy to reason code’s purpose ▫ Doesn’t drift like code comments
  7. 7. How do we evaluate programming languages?
  8. 8. We Evaluate Languages By… 1. Domain 2. Community 3. Type System
  9. 9. The More You Use Your Type System The More It Works For You
  10. 10. The More You Use Your Type System The More It Works For You If you just use primitive types, don’t expect much more than primitive behavior from your type system. Use rich types to describe your domain, and you’ll find your type system actually enforcing your domain!
  11. 11. Expectations of This Talk
  12. 12. 1. Only scratching the surface 2. Not going deep into type theory 3. Code examples biased towards Scala but concepts apply to many languages Comic by Cassandra Calin
  13. 13. Fundamental Type System Classifications
  14. 14. Fundamental Type System Classifications ◦ Type Safety ◦ Static vs Dynamic Type Checking ◦ Type Inference
  15. 15. Type Safety “A safe language is one that protects its own abstractions.” - Pierce (TaPL)
  16. 16. Type Safety Unsafe Behavior ● Dereferencing null pointer ● Accessing array out of bounds ● Using uninitialized variables ● Casting between types ● Not checking parameter lists Safe Behavior ● Runtime Exceptions ○ NullPointerException ○ ArrayIndexOutOfBoundsException ● Not allowing uninitialized variables ● Compile time parameter list agreement checks
  17. 17. Type Safety Unsafe Behavior ● Dereferencing null pointer ● Accessing array out of bounds ● Using uninitialized variables ● Casting between types ● Not checking parameter lists Safe Behavior ● Runtime Exceptions ○ NullPointerException ○ ArrayIndexOutOfBoundsException ● Not allowing uninitialized variables ● Compile time parameter list agreement checks Type safety is not binary. Languages vary in safety on a per feature basis (e.g. memory safety, abstraction safety, runtime safety, cast safety, etc.)
  18. 18. Static vs Dynamic Static Type Checking Verify safety of program before execution. Dynamic Type Checking Verify safety of program at execution.
  19. 19. Question: Why do people get into religious arguments over static vs dynamic type checking?
  20. 20. Kidding! More seriously, what some of the pros/cons of static vs dynamic type systems?
  21. 21. Static vs Dynamic Static Type Checking ◦ Early feedback ◦ More reliable ◦ More optimizable ◦ Longer edit-compile-test cycle Dynamic Type Checking ◦ Shorter edit-compile-test cycle ◦ More flexible ◦ Good for prototyping ◦ Better at metaprogramming ◦ Get ready for lots and lots of unit testing
  22. 22. Static vs Dynamic: Language Examples Static ◦ C ◦ C++ ◦ Java ◦ C# ◦ Scala ◦ Haskell ◦ Rust ◦ Kotlin ◦ Go Dynamic ◦ JavaScript ◦ Ruby ◦ Python ◦ Perl ◦ PHP ◦ Lisp ◦ Clojure ◦ R ◦ Bash
  23. 23. Dynamic Static Weak Strong Erlang Clojure Python Groovy Ruby Magik Perl VB PHP JavaScript C# F# Haskell Scala Java C C++
  24. 24. Type Inference Automatic detection of data type ◦ Feature of some strongly statically typed languages ◦ Especially prevalent in functional programming languages Explicitly Type Annotated Type Inference val x: Int = 100 val y: Seq[String] = Seq(“apple”, “orange”) val z: User = new User(“Jordan Parmer”) val a: Option[String] = findKey(“type”) val x = 100 val y = Seq(“apple”, “orange”) val z = new User(“Jordan Parmer”) val a = findKey(“type”)
  25. 25. Type Inference Automatic detection of data type ◦ Feature of some strongly statically typed languages ◦ Especially prevalent in functional programming languages Explicitly Type Annotated Type Inference val x: Int = 100 val y: Seq[String] = Seq(“apple”, “orange”) val z: User = new User(“Jordan Parmer”) val a: Option[String] = findKey(“type”) val x = 100 val y = Seq(“apple”, “orange”) val z = new User(“Jordan Parmer”) val a = findKey(“type”) Still statically typed at compile time
  26. 26. Strong type inference paves the way for expressions over statements.
  27. 27. Type Driven Development Focus on type signatures instead of implementation. With pure- ish functional languages, if it compiles, you know it is likely correct. Lets you fill in the details later.
  28. 28. Rich Type System Features
  29. 29. Functions as Types Higher Order Functions
  30. 30. Higher Order Functions Function that either takes another function as an argument and/or returns a function as its result.
  31. 31. Higher Order Functions Function that either takes another function as an argument and/or returns a function as its result.
  32. 32. Higher Order Functions Function that either takes another function as an argument and/or returns a function as its result. Partial function application via currying Returns String => String
  33. 33. Question: So what is the problem with conditionals anyway? #ConditionalsAreEvil
  34. 34. Algebraic Data Types
  35. 35. Algebraic Data Types A variant/union type that supports sum and product algebras. Pattern matching capabilities on type shape. ◦ Sum is alternation A | B, meaning A or B but not both ◦ Product is combination A B, meaning A and B together
  36. 36. Algebraic Data Types A variant/union type that supports sum and product algebras. Pattern matching capabilities on type shape. Product Types (A AND B) ◦ Tuples: (Int, Boolean) ◦ Classes: class Foo(x: Int, y: String)
  37. 37. Algebraic Data Types A variant/union type that supports sum and product algebras. Pattern matching capabilities on type shape. Sum Types (A OR B NOT BOTH) ◦ Option[T] (Some | None) Maybe[T] (Just | Empty) ◦ Either[B, A] (Left | Right) ◦ Try[T] (Success | Failure)
  38. 38. Algebraic Data Types Example ADT of Sum Type
  39. 39. Algebraic Data Types Example ADT of Sum Type If we don’t include a case for one of the members of the ADT, we get a compiler warning. Called exhaustive checking.
  40. 40. ADT’s of the sum algebra look like ‘enum’ types from C/C++ but those languages internally treat them as integers. These are more sophisticated taking custom type shapes.
  41. 41. Polymorphism Higher abstractions with type safety
  42. 42. Polymorphism Parametric Polymorphism Subtype Polymorphism Ad-Hoc Polymorphism (aka Type Classes)
  43. 43. Question: When people talk about polymorphism, what kinds of problems are they trying to solve?
  44. 44. Parametric Polymorphism Same as generic types from C#, Java. Types are parameterized.
  45. 45. Parametric Polymorphism
  46. 46. Parametric Polymorphism
  47. 47. Parametric Polymorphism
  48. 48. Parametric Polymorphism
  49. 49. Parametric Polymorphism
  50. 50. Parametric Polymorphism Bounds Checking ◦ Upper bounds (supertype) ◦ Lower bounds (subtype)
  51. 51. Partial Orders (from Order Theory) A partial order is a binary relation <: over a set P. When a <: b, we say that a is related to b but does not imply b is related to a.
  52. 52. Upper Bounds Checking
  53. 53. Lower Bounds Checking
  54. 54. Existential Types When you need a parameterized type but you don’t care what it is.
  55. 55. Existential Types We need [T] so we can support any “List of type T” but we don’t actually need to use ‘T’ in the implementation.
  56. 56. Existential Types We need [T] so we can support any “List of type T” but we don’t actually need to use ‘T’ in the implementation.
  57. 57. Type Variance
  58. 58. What if we want to model a factory that creates vehicles?
  59. 59. Invariant
  60. 60. Invariant
  61. 61. Covariant
  62. 62. Covariant
  63. 63. Covariant One more example:
  64. 64. What if we want to limit the models the factory is able to produce? Let’s say we can make vehicles as long as the model isn’t too specialized. In other words, control the direction of the specialization. “Up to this point and no further”.
  65. 65. Contravariant
  66. 66. Contravariant
  67. 67. When is contravariant subtyping actually practical?
  68. 68. Practical Contravariant Example trait Function1[-P, +R] { def apply(p: P): R } Function1[GrandParent, Child] <: Function1[Parent, Parent] Functor A => B Helpful Explanation: https://www.atlassian.com/blog/software-teams/covariance-and-contravariance- in-scala Inputs for A can only have fewer requirements. Outputs for B must at least be as specialized as B since caller expects all of B to be available.
  69. 69. Type Classes Ad-hoc Polymorphism
  70. 70. What are disadvantages to OOP inheritance?
  71. 71. Inheritance Disadvantages ◦ Violates encapsulation ◦ Layers and layers of state ◦ Difficult to follow hierarchy ◦ Re-use abuse (we bad at correct DRY) ◦ Can’t expand behavior if you don’t own codebase (e.g. libraries)
  72. 72. What are common alternatives to inheritance?
  73. 73. Composition over inheritance is one.
  74. 74. Another Way To Approach This?
  75. 75. How about adding behavior to types we don’t own?
  76. 76. How about selectively applying behaviors in different scopes of our code base?
  77. 77. How about applying lawful behaviors to abstractions?
  78. 78. Type classes are the answer
  79. 79. Separation of Data from Behavior
  80. 80. Separation of Data from Behavior Could implement interfaces and traits… ...but what about cases where we don’t own the code base?
  81. 81. Elements of a type class 1. The type class itself (desired behavior) 2. Instances of particular types (implementation of behavior) 3. Interface or API exposed to users
  82. 82. Behavior Implementation for Integer Implementation for Boolean Implementation for User Implementation for Record Implementation for Json Function Requiring Type with Behavior
  83. 83. How Is This Different From Interfaces In OOP?
  84. 84. Behavior Implementation for Integer Implementation for Boolean Implementation for User Implementation for Record Implementation for Json Function Requiring Type with Behavior Compiler error if calling function with type that doesn’t implement behavior.
  85. 85. Behavior Implementation for Integer Implementation for Boolean Implementation for User Implementation for Record Implementation for Json Function Requiring Type with Behavior Implementations can be imported into specific scopes.
  86. 86. Behavior Implementation for Integer Implementation for Boolean Implementation for User Implementation for Record Implementation for Json Function Requiring Type with Behavior Implementations can be provided for types we don’t own or have access to code.
  87. 87. Behavior Implementation for Integer Implementation for Boolean Implementation for User Implementation for Record Implementation for Json Function Requiring Type with Behavior We can easily drop in new implementations. Implementation for NewThing
  88. 88. With type classes we flip the thinking; instead of types carrying behaviors, we have templates of behaviors with interpretations for different types.
  89. 89. 1. The Type Class (Desired Behavior) This is the actual behavior: A => Json Code provided by Noel Welsh and Dave Gurnell in book “Scala with Cats”
  90. 90. 2. Type class instances (implementations of behavior) Code provided by Noel Welsh and Dave Gurnell in book “Scala with Cats”
  91. 91. 3. Type class access (api to caller) The compiler finds our implicit behavior in scope (because of the localized import) and uses the type’s implementation in the type class. Code provided by Noel Welsh and Dave Gurnell in book “Scala with Cats”
  92. 92. Disadvantages? ● Verbose if language doesn’t have native support ○ Haskell has native support ○ Scala does not and requires implicit boilerplate code ● Paradigm shift from traditional OOP/interfaces
  93. 93. Examples ● Haskell ○ It’s type classes all the way down ● Scala ○ ScalaZ ○ Cats
  94. 94. Higher Kinded Types ...another talk...another day...
  95. 95. Thanks! ANY QUESTIONS? You can find me on Twitter/LinkedIn at @ProfParmer Jordan Parmer

×