什么是“多重排列代数”,我如何用它来解决“真正的问题”?

时间:2010-09-20 16:28:56

标签: algebra

显然,Alexander Stepanov在interview中声明了以下内容:

“我发现OOP [面向对象编程]在技术上不合理。它试图根据在单一类型上变化的接口来分解世界。 要处理真正的问题,你需要多重代数 - 跨越多种类型的接口系列。 [强调添加。]

暂时忽略他关于OOP的陈述,除了他的简洁定义之外,什么是“多重代数”,你能否给出一个如何使用它们的实际例子(用你选择的语言)?

3 个答案:

答案 0 :(得分:23)

我相信他正在谈论泛型编程(他coined the term),无论是在本次STL谈论的背景下,还是“在意大利”,意思是:

  1. 针对界面进行编程,该界面描述的内容可能适合所有(并且希望有几种)类型(因此是多重排序的), ...
  2. ... 提供他们有一些属性,通常是关于该类型元素(因此代数)的某些操作的性质。
  3. 要做(1),你需要有办法指定一个类型为参数的程序,即多态,并做(2) ,您需要一种方式来表示您希望该类型带有特定操作(并且,如果您可以表达它们,属性)。实际上,您通过其操作的数据的结构对您的程序进行参数化。范式在某些地方被称为有界多态,数据类型 - 泛型编程,......这反映出语言对如何实现该想法有不同的概念 - 因此上面的斜体“类型”。

    • 对于C ++来说,似乎至少是Stepanov-这对应于模板(尽管有关如何做到最好的想法are still evolving)。
    • 对于OO语言(Generic Java,C#),类型参数的约束通常使用子类型边界('有界通配符'...)表示。
    • 对于Haskell或Scala,您(分别和类似地)类型暗示
    • ML系列语言更喜欢使用 modules
    • 请注意,一些proof assistants(可以表达'诚实上帝'属性作为类型)已经形成了类型类的风格:Isabelle,Coq,Matita就是这样实例

    请注意,Stepanov只是共同编写了an entire book,对图书馆进行了详尽的开发,该图书馆体现了完全他认为的意思。因此,如果您想在C ++ 中使用示例,这绝对是您应该查看的地方。另请注意,这比coding against an interface, rather than an object的现有常见建议更为进化。

    通过“实际例子”,我不知道你的意思是“如何”或“为什么”使用它。为了快速回答“为什么”,通用性很好,因为它有点像普通的多态,它可以让你重用代码。但是,更重要的是:

    1. 必须使用每个单一类型的多态代码通常无法做任何有趣的事情,而拥有一个受限制的界面可以让你编写更丰富的程序

      < / LI>
    2. 通过指定界面如何适合您的某些数据,您可以选择一种类型安全的方法来选择那些符合您需求的元素。例如,您可能知道 reduction 运算符(Python和Hadoop的reduce,一堆函数语言的fold)只有在其中的顺序可并行化你应用缩减函数无关紧要(+xminand起作用,但设置差异不起作用。如果你有一个'类型配备关联操作'的概念,你知道你可以调用并行缩减。

    3. 通用性产生的任何开销都发生在编译时。例如,模板快速传播

    4. 如果您已经看过一些通用Java,请查看Comparable通用接口。它只定义了一个操作,但它所做的合约虽然是基本的,但它具有很强的代数特征。我引用:

        

      对于数学倾向,定义给定类C的自然排序的关系是:

        {(x, y) such that x.compareTo((Object)y) <= 0}.
      
           

      此总订单的商是:

        {(x, y) such that x.compareTo((Object)y) == 0}.
      
           

      紧接着来自compareTo的合同,商是C上的等价关系,&gt;并且自然顺序是C上的总顺序。

      现在,我可以编写一个方法来选择最小值,一次,并将其用于适合此接口的任何类型

       public static <T extends Comparable<T>> T min (T x, T y) {
         if (x.compare(y) < 0) x; else y;
       }
      

      当然,由于程序化构造实现的方式变化很大,因此在可用性和可用性方面会得到什么。表现力也会有所不同。也许您不应仅仅通过C ++或Java等OO语言来判断数据通用编程 - 但是我已经编写了太多文件归属或类型类的自动实例生成。

答案 1 :(得分:9)

我太晚了,但也许对你有所帮助。用户huitseeker从软件设计的角度写了一个很好的答案。我想从数学的角度回答你的问题。在深入软件世界之前,Alex Stepanov是一位数学家,研究过abstractuniversal代数。他经常试图将严谨的数学基础带入软件和算法设计领域。在他的书From Mathematics to Generic ProgrammingElements of Programming中,他主张这种设计实践。他关于混合algebraic structures概念和软件设计的想法是在generic programming的概念中实现的。现在让我们来谈谈他的话:

  

要处理真正的问题,你需要多重代数 - 跨越多种类型的接口系列

在我看来,他想在这里提到两个主要概念:abstract data typeADT)和algebraic structure的想法。 第一个概念:ADTADT - 是数据类型的数学模型,其中数据类型仅由其语义定义。 Stepanov将ADT的概念与OOP意义上的object概念进行了对比。对象包含数据和状态,而ADT - 。 ADT - 是behavioural abstractionoperation cluster,用于描述与数据的互动。行为抽象完全通过抽象数据类型的代数规范来描述。您可以在原始的Liskov and Zilles论文中详细了解这一点,我也建议您Object-Oriented Programming Versus Abstract Data Types撰写论文William R. Cook

Discalimer 你可以跳过这一段,因为它更多&#34;数学而不是那么重要&#34; )起初我想澄清一些术语。当我谈到algebraic structure时,它与代数相同。对于代数结构,单词algebra通常为also used。更准确地说,当我们谈论代数结构(代数)时,我们通常意味着algebra over an algebraic theory。有一个variety of algebras的概念,因为在某个类别的对象上有几个代数结构的概念。根据定义,algebraic theory(代数)包含这些操作必须满足的操作和规则的规范:这是我们将使用的代数结构的工作定义,我认为这个定义,Stepanov隐含地在报价中提到。 Stepanov想提到的第二个概念是ADT的最有趣的属性:它们可以直接正式建模为many-sorted algebraic structures。让我们更正式地谈谈它。代数结构 - 是carrier set,其上定义了一个或多个有限运算。这些操作通常不是在一组上定义,而是在多组上定义。例如。让我们定义和代数来模拟字符串连接。这个代数将不是通过一组字符串定义,而是超过两组:字符串集S和自然数集N,因为我们可以定义一个操作,它可以将字符串与自身连接一些有限数量的字符串倍。因此,此操作将采用两个操作数,这两个操作数属于不同的基础(载体)集:SN。设置在代数中定义这些不同的操作数(它们的类型)称为一组sortsSort是该类型的代数模拟。具有多种排序的代数称为多分类代数。在通用代数中,signature列出了表征代数结构的运算。多排序的代数结构可以具有任意数量的域。这些类型是签名的一部分,它们扮演着不同域名的角色。许多排序的签名还规定了定义多排序代数结构的功能和关系的排序。对于一个有序的各种代数,签名是一个集合,其元素称为操作,每个元素都被赋予一个称为arity的基数(0,1,2,...)。多重排序代数的签名可以定义为Σ = (S,OP,A),其中S - 排序名称(类型)集,OP - 操作名称集和A - arities和以前一样,除了现在arity是输入排序的列表(sequence或更一般地free monoid)而不仅仅是自然数(列表的长度)和一个输出排序。现在我们可以创建一个抽象数据类型ADT的代数规范作为三元组:

ADT = (N, Σ, E)

,其中N - 抽象数据类型的名称,Σ = (S,OP,A) - 多重排序代数结构的签名,E = {e1, e2, …,en} - 是签名中的等式的有限集合。你现在可以看到我们对ADT有严格的数学描述。在数学中,许多分类的代数结构通常被用作方便的工具,即使只需要一点点努力就可以避免它们。许多排序的代数结构很少以严格的方式定义,因为明确地执行泛化是直截了当的。这就是为什么多分类代数的理论可以成功地应用于软件设计的原因。

因此,Alex Stepanov想说他更喜欢ADT和泛型编程而不是OOP,因为我们可以创建具有严格的数学/代数基础的程序。我非常感谢他的努力。我们都知道代数设计总是正确,严谨,美观,简单,给我们更好的抽象。

答案 2 :(得分:0)

并不是说我是这方面的理论专家,而是让我们看看引用,以便我可以尝试将我的实际理解添加到讨论中。

  

要处理真正的问题,你需要多重代数 - 跨越多种类型的接口系列。

从我的阅读中,我认为跨越多种类型的接口系列听起来很像Haskell中的类型类,类似于C ++中的概念。采用像Foldable这样的类型类,它实际上是一个类型参数化接口,即。一系列跨越多种类型的接口。那么关于如何解决多重代数问题的问题,如果你把它理解为类型类或概念,泛型编程就是关于这一点。