Scala 函数式程序设计原理(4)--Types and Pattern Matching

4.1 Objects Everywhere

Pure Object Orientation:

A pure object-oriented language is one in which every value is an object.

If the language is based on classes, this means that the type of each value is a class.

4.2 Functions as Objects

(x: Int) => x * x
is expanded to:
{ class AnonFun extends Function1[Int, Int] {
  def apply(x: Int) = x * x
  }
  new AnonFun
}
or, shorter, using anonymous class syntax:
new Function1[Int, Int] {
  def apply(x: Int) = x * x
}

 Note that a method such as

def f(x: Int): Boolean = ...

 is not itself a function value.

But if f is used in a place where a Function type is expected, it is converted automatically to the function value

(x: Int) => f(x)

 or, expanded:

new Function1[Int, Boolean] {
    def apply(x: Int) = f(x)
}

 eta-expansion: the transformation that converts the name F to this anonymous function, is called in lambdacalculus, eta expansion.

4.3 Subtyping and Generics

  • S <: T means: S is a subtype of T, and
  • S >: T means: S is a supertype of T, or T is a subtype of S.

[S >: NonEmpty <: IntSet]

would restrict S any type on the interval between NonEmpty and IntSet.

The Linkov Substitution Principle:

The following principle, started by Barbara Liskov, tell us when a type can be a subtype of another.

  If A <: B, then everything one can to do with a value of type B one should also be able to do with a value of type A.

The actual definition Liskov used is a bit more formal. It says:

  Let q(x) be a property provable about objects x of type B. Then q(y) should be provable for objects y of type A where A <: B.

4.4 Variance

Say C[T] is a parameterized type and A,B are types such that A <: B.

In general, there are three possible relationships between C[A] and C[B]:

C[A] <: C[B]                     C is covariant

C[A] >: C[B]                     C is contravariant

neither C[A] nor C[B] is a subtype of the other    C is nonvariant

Scala lets you declare the variance of a type by annotating the type parameter:

class C[+A] { ... }  C is covariant

class C[-A] { ... }   C is contravariant

class C[A] { ... }   C is nonvariant

Typing Rules for Functions

Generaly, we have the following rulw for subtyping between function types:

  if A2 <: A1 and B1 <: B2, then

  (A1 => B1) <: (A2 => B2)

So functions are contravariant in their argument type(s) and covariant in their result type.

  • covariant type parameters can only appear in method results
  • contravariant type parameters can only appear in method parameters
  • invariant type parameters can appear anywhere

4.5 Decomposition

4.6 Pattern Matching

Match Syntax:

Rules:

  • match is followed by a sequence of cases, pat => expr.
  • Each case associates an expression expr with a pattern pat.
  • A MarchError exception si thrown if no pattern matches the value of the selector.
e match {
    case pat1 => expr1
     ...   ...
  case patn => exprn }

 What Do Patterns Match?

  • A constructor pattern C(p1, ..., pn) matches all the values of type C (or a subtype) that have been constructed with arguments matching the patterns p1, ..., pn.
  • A variable pattern x matches any value, and binds the name of the variable to this value
  • A constant pattern c matches values that are equal to c( in the sense of ==)

4.7 Lists

The list is a fundamental data structure in functional programming.

A list having x1, ..., xn as elements is written List(x1, ..., xn)

原文地址:https://www.cnblogs.com/PaulingZhou/p/6874806.html