• Coursera Programming Languages, Part A 华盛顿大学 Week 4


    Week 4 我们主要介绍 type inference 和 module 系统。

    What is type inference?

    对于 静态类型语言 (Statically typed languages) 如 ML,Java 与 C,每一个 binding 的类型是在编译时确定的。type-checker 在编译时决定是否要运行整个程序。与之不同的是动态类型语言 (Dynamically typed languages) 例如 Racket,Ruby 与 Python。
    ML 语言又和其他静态类型语言不同,它是 隐式类型的 (implicitly typed),意味着编写程序时我们很少需要直接声明 bindings 的类型,type-checker 推断出我们想要的类型。当某些函数的参数或者返回值可以是任何一种类型时,type-checker 会向它们分配多态类 'a, 'b, 'c... 这体现了 ML 语言类型推断与参数化多态 (parametric polymorphism) 的融合。


    Overview of the type inference

    • It determines the types of bindings in order. 使用之前的 binding types 来推断之后的 binding types
    • 对于每个 fun val bindings, 分析一些 necessary fact 来决定 binding 的类型。例如,当我们发现表达 x+1 时,可以确认 x 一定是 int type。
    • 对于任何 函数参数或是返回值中的 unconstrained types,分配多态类型 'a, 'b, 'c...
    • 执行 value restriction
    • 若不存在某一种 solution,不执行该程序并抛出 type error

    关于 value restriction

    当 可变类型 reference 与 多态类结合时,存在一种情况能够破坏我们目前已知的 type inference 系统。

    val r = ref NONE         
    (* a val binding : r has the type 'a option reference *)
    val _ = r := SOME "hi"   
    (* type check operator := : instantiate (but do not change) 'a with string, type checked *)
    val i = 1 + valOf (!r)   
    (* type check operator ! : 'a option reference => 'a option, type check func valOf : 'a option => 'a, instantiate 'a with int, type checked *)
    (* though the above 3 lines all type checked, it use + to add a int and a string *)
    

    为了解决这个问题,ML 采用了 value restriction 的方法:只有 val x = e 中的 e 是一个 value 或者是一个 valuable 时才有可能分配多态类型给 x。在上面的例子中,ref NONE 是一个函数调用,是需要计算的,不属于 value 或 valuable,因此系统拒绝给 r 分配多态类,取而代之的是所谓的 "dummy type : ?X1 option ref" 而不是一个类型变量。dummy type 在接下来的语句中将不能 type check。
    value restriction 的存在解决了以上这个问题,但同时也使得某些 partial application 与 currying 的结合无法实现。


    Mutual recursion

    使用 and 关键字来链接需要相互调用的函数。


    Modules for namespace management

    一个好的程序应当是模块化的。我们将所有的 bindings 按照其功能分成不同的类并归于对应的 namespace module。这使得程序更加模块化并且能够避免由于变量名称相同引起的 shadowing。
    我们用关键字 structure 来定义一个包含众多 bindings 的 module。格式如下 structure ModuleName = struct bindings end
    module 内部同样遵循 lexical scope 等规则。在 module 外部需要调用内部的 binding b 时,使用 ModuleName.b 的形式。


    Signatures

    目前为止,structures 提供了 namespace management 的能力,这非常有用,但是本质上并没有改变程序的功能。
    如果我们赋予 structure 签名 (signature, which are types for module),可以对模组外部代码调用模组内部模块是提供严格的限制,也就是说,我们可以创造 structure 的接口 (interface)。
    这对我们实现抽象化数据结构等功能十分有用。
    如以下代码:

    signature MATHLIB =
    sig
    val fact : int -> int
    val half_pi : real
    val doubler : int -> int
    end
    structure MyMathLib :> MATHLIB =
    struct
    fun fact x =
      if x=0
      then 1
      else x * fact (x - 1)
    val half_pi = Math.pi / 2.0
    fun doubler y = y + y
    end
    

    因为 :> MATHLIB, 只有当 structure MyMathLib 正确提供了 signature MATHLIB 中声明的所有内容时才能 type check。MATHLIB 还可以声明各种 datatype,exception 等内容。


    Use signature to create private parts

    在模组外部的代码无论如何也不能调用模组内部未被 signature 声明的内容。这一点可以很好的运用在抽象数据结构的实现中。我们只将用户需要调用的一些函数做成接口,其余的实现可以全部隐藏,这样就能大大减少出现用户进行不合法调用的可能性。
    我们要确保 signature 一定提供所有用户所需要的信息:在此基础上,尽量减少要提供的信息量。


    Rules for signature matching

    structure NAME match signature BLAH :

    • 对于 BLAH 中声明的每个 val-binding,NAME 中必须有相同 type 或者 more general type 的对应 binding
    • 对于 BLAH 中声明的每个非抽象的 type-binding,NAME 必须有相同的 type-binding
    • 对于 BLAH 中声明的每个抽象 type-binding, NAME 必须创建对应的 type (通过 datatype binding or type synonym)
    • 注意 NAME 可以含有 BLAH 中未声明的 binding,只是这些 binding 不能在外部被调用

    Equivalent implementation and programming without side-effect

  • 相关阅读:
    有关TSQL的10个好习惯
    jQuery操作Select
    SQL Server 高性能写入的一些总结
    如何限制文本框只能输入数字,小数点,英文,汉字等各类代码(转载)
    补码、条件跳转指令
    Windows获取进程完整路径
    NumPy库
    WS_窗口风格常量
    C语言核心技术第一章
    Ubuntu安装搜狗输入法
  • 原文地址:https://www.cnblogs.com/VeniVidiVici/p/16104557.html
Copyright © 2020-2023  润新知