SML如何实现抽象?

SML如何实现抽象?,sml,Sml,我是SML的新手,这是我第一次学习函数式语言。我认为SML是抽象的。我还没有找到关于如何在SML中实现抽象的完美解释。有人能提供解释吗?SML程序通常是建立在描述当前问题类型的基础上的。然后,该语言使用模式匹配来确定您正在处理的案例 datatype Shape = Circle of real | Rectangle of real*real | Square of real val a = Circle(0.2) val b = Square(1.3) val c = Rectangle(

我是SML的新手,这是我第一次学习函数式语言。我认为SML是抽象的。我还没有找到关于如何在SML中实现抽象的完美解释。有人能提供解释吗?

SML程序通常是建立在描述当前问题类型的基础上的。然后,该语言使用模式匹配来确定您正在处理的案例

datatype Shape = Circle of real | Rectangle of real*real | Square of real

val a = Circle(0.2)
val b = Square(1.3)
val c = Rectangle(4.0,2.0)

fun area (Circle(r)) = 3.14 * r * r
  | area (Square(s)) = s * s
  | area (Rectangle(b,h)) = b * h
这有助于解释sml吗?

在sml中,您可以通过使用代数数据类型和签名等组合来定义“抽象”

代数数据类型允许您定义特定于问题域的新类型,签名允许您提供这些类型的功能/行为,并提供实现信息隐藏、可扩展性和可重用性的方便方法


结合这些东西,您可以创建“抽象”,其实现细节对您隐藏,您只需通过它们的公共接口(无论签名公开什么)就可以理解

一般来说,编程中至少有两种形式的“抽象”:

  • 提取客户机(参数化)
  • 抽象实现(封装)
(如果你在意的话,这些对应于逻辑和类型理论中普遍存在的量化。)

在ML中,参数化可以在两个级别上完成。无论是在小型应用程序中,还是在使用函数(对值的抽象)和多态性(对类型的抽象)。请特别注意,函数是一流的,因此可以将一个函数参数化,而不是将另一个函数参数化。例如:

fun map f []      = []
  | map f (x::xs) = f x :: map f xs
摘要列出了转换函数
f
上的转换以及元素类型

大体上,可以使用模块系统进行参数化:函子将整个模块抽象到另一个模块上(即值和类型上)。例如,您还可以将map函数编写为函子:

functor Mapper(type t; type u; val f : t -> u) =
struct
  fun map []      = []
    | map (x::xs) = f x :: map xs
end
signature ORD =
sig
  type t
  val compare : t * t -> order
end

signature SET =
sig
  type elem
  type set
  val empty : set
  val add : elem * set -> set
  val mem : elem * set -> bool
end

functor Set(Elem : ORD) :> SET where type elem = Elem.t =
struct
  type elem = Elem.t
  datatype set = Empty | Branch of set * elem * set

  val empty = Empty

  fun add(x, Empty) = Branch(Empty, x, Empty)
    | add(x, Branch(l, y, r)) =
      case Elem.compare(x, y) of
        LESS => Branch(add(x, l), y, r)
      | EQUAL => Branch(l, y, r)
      | GREATER => Branch(l, y, add(x, r))

  fun mem(x, Empty) = false
    | mem(x, Branch(l, y, r)) =
      case Elem.compare(x, y) of
        LESS => mem(x, l)
      | EQUAL => true
      | GREATER => mem(x, r)
end
但通常情况下,在大规模抽象中使用函子,也就是说,在需要参数化的函数不止一个的情况下

封装也是通过使用模块来实现的。具体来说,通过密封它们,即在签名后面隐藏其类型的详细信息。例如,下面是整数集的(简单)实现:

signature INT_SET =
sig
  type set
  val empty : set
  val add : int * set -> set
  val mem : int * set -> bool
end

structure IntSet :> INT_SET =  (* ':>' hides the implementation of type set *)
struct
  type set = int list
  val empty = []
  fun add(x, s) = x::s
  fun mem(x, s) = List.exists (fn y => y = x) s
end
在结构
IntSet
之外,其类型
set
是完全抽象的,即不能与列表互换。这就是所谓的模块密封操作器的用途

这两种形式的抽象可以同时发生。例如,在ML中,通常将集合实现为函子:

functor Mapper(type t; type u; val f : t -> u) =
struct
  fun map []      = []
    | map (x::xs) = f x :: map xs
end
signature ORD =
sig
  type t
  val compare : t * t -> order
end

signature SET =
sig
  type elem
  type set
  val empty : set
  val add : elem * set -> set
  val mem : elem * set -> bool
end

functor Set(Elem : ORD) :> SET where type elem = Elem.t =
struct
  type elem = Elem.t
  datatype set = Empty | Branch of set * elem * set

  val empty = Empty

  fun add(x, Empty) = Branch(Empty, x, Empty)
    | add(x, Branch(l, y, r)) =
      case Elem.compare(x, y) of
        LESS => Branch(add(x, l), y, r)
      | EQUAL => Branch(l, y, r)
      | GREATER => Branch(l, y, add(x, r))

  fun mem(x, Empty) = false
    | mem(x, Branch(l, y, r)) =
      case Elem.compare(x, y) of
        LESS => mem(x, l)
      | EQUAL => true
      | GREATER => mem(x, r)
end

集合的这种实现适用于可以提供排序函数的任何类型。与以前的朴素实现不同,它还使用更高效的搜索树作为实现。但是,这在外部是不可见的,因为类型的实现再次被隐藏。

您能更详细地解释一下“抽象”是什么意思吗?