如何在 Haskell 中建模类层次结构?

2024-04-18

我是一名 C# 开发人员。来自面向对象的世界,我从接口、类和类型层次结构的角度开始思考。由于 Haskell 缺乏面向对象,有时我发现自己陷入困境,无法想出用 Haskell 建模某些问题的方法。

如何在 Haskell 中对涉及类层次结构的现实世界情况进行建模,如下所示:http://www.braindelay.com/danielbray/endangered-object-orient-programming/isHierarchy-4.gif http://www.braindelay.com/danielbray/endangered-object-oriented-programming/isHierarchy-4.gif


首先:标准的面向对象设计在 Haskell 中不能很好地工作。你可以对抗语言并尝试做出类似的东西,但这将是一种挫败感的练习。所以第一步是为你的问题寻找 Haskell 风格的解决方案,而不是寻找在 Haskell 中编写 OOP 风格解决方案的方法.

但这说起来容易做起来难!从哪里开始呢?

因此,让我们拆解 OOP 为我们所做的事情的具体细节,并思考这些细节在 Haskell 中会是什么样子。

  • Objects:粗略地说,对象是一些数据和操作该数据的方法的组合。在 Haskell 中,数据通常使用以下方式构建:代数数据类型;方法可以被认为是将对象的数据作为初始隐式参数的函数.
  • Encapsulation: However, the ability to inspect an object's data is usually limited to its own methods. In Haskell, there are various ways to hide a piece of data, two examples are:
    • 在不导出类型构造函数的单独模块中定义数据类型。只有该模块中的函数可以检查或创建该类型的值。这有点类似于protected or internal成员。
    • 使用部分应用程序。考虑功能map它的论点被翻转了。如果您将其应用于列表Ints,你会得到一个类型的函数(Int -> b) -> [b]。从某种意义上说,您提供的列表仍然“在那里”,但除了通过该函数之外,没有其他东西可以使用它。这相当于private成员,并且部分应用的原始函数与 OOP 风格的构造函数相当。
  • “临时”多态性:通常,在面向对象编程中,我们只关心某个东西实现了一个方法;当我们调用的时候,具体调用的方法是根据实际的类型来确定的。 Haskell 提供类型类用于编译时函数重载,这有多种方式more比 OOP 语言灵活。
  • 代码复用:老实说,我的观点是通过继承重用代码过去和现在都是一个错误。在 Ruby 之类的东西中发现的 Mix-ins 让我觉得这是一个更好的 OO 解决方案。无论如何,在任何函数式语言中,标准方法是使用高阶函数分解常见行为,然后专门化通用形式。一个经典的例子是fold函数,它概括了几乎所有迭代循环、列表转换和线性递归函数。
  • Interfaces: Depending on how you're using an interface, there are different options:
    • 解耦实施:具有类型类约束的多态函数就是您想要的。例如,函数sort有类型(Ord a) => [a] -> [a];它与您提供的类型的详细信息完全解耦,除了它必须是某种类型实现的列表之外Ord.
    • 通过共享接口处理多种类型:为此,您需要语言扩展存在类型,或者为了简单起见,使用一些变体部分应用如上所述,您可以提前应用函数并处理结果,而不是对其应用值和函数。
  • 子类型化,又名“is-a”关系:这是你最不走运的地方。但是,根据多年的专业 C# 开发人员经验来看,在某些情况下,您确实need子类型并不是很常见。相反,请考虑上述内容,以及您试图通过子类型化关系捕获什么行为。

您可能还会发现这篇博文 http://blog.ezyang.com/2010/05/design-patterns-in-haskel/有帮助;它快速总结了在 Haskell 中使用什么来解决 OOP 中经常使用的一些标准设计模式的相同问题。

作为最后的附录,作为一名 C# 程序员,您可能会发现研究它与 Haskell 之间的联系很有趣。相当多负责 C# 的人也是 Haskell 程序员,并且 C# 最近添加的一些内容深受 Haskell 的影响。最值得注意的可能是 LINQ 底层的单子结构,IEnumerable 本质上是列表单子。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Haskell 中建模类层次结构? 的相关文章

  • 如何将一个窗格连接到另一个窗格

    如何将输出连接到paneWithList PaneWithList其上有一个监听器JList以便将所选行输出到控制台 我怎样才能将该输出定向到JTextPane关于输出 Could PaneWithList触发一个事件Main拿起 会属性更
  • PHP - 多个不同的数据库依赖注入类

    我花了过去几个小时试图找到 最佳 最合乎逻辑的方法的答案 以编写一个 php 数据库类以同时连接到一个 postgresql 数据库和一个 mysql 数据库 另外 我想采用依赖注入设计 但对整个概念还是陌生的 到目前为止我已经想出了 cl
  • 在 Haskell 中阅读 GraphML

    我正在尝试将包含单个有向图的 GraphML 文件读入 HaskellData Graph http hackage haskell org package containers 0 2 0 1 docs Data Graph html为了
  • Haskell:Where 与 Let

    我是 Haskell 的新手 我很困惑Where vs Let 它们似乎都提供了相似的目的 我读过一些比较Where vs Let但我很难辨别何时使用它们 有人可以提供一些背景信息或者一些示例来说明何时使用其中一种而不是另一种吗 哪里与让
  • Accelerate 和 Repa 是否有不同的用例?

    我一直在玩 Repa 和 Accelerate 它们都很有趣 但我不知道何时使用其中一个 何时使用另一个 他们是一起成长 是竞争对手 还是只是为了解决不同的问题 Repa 是一个用于高效数组构建和遍历的库 用 Haskell 编程并在 Ha
  • 是否可以列出派生 Generic 的记录数据类型中字段的名称和类型?

    我知道对于派生 Data Data 的数据类型 constrFields http hackage haskell org package base 4 7 0 2 docs Data Data html v constrFields给出字
  • 让 GHC 生成“带进位加法 (ADC)”指令

    下面的代码将表示 192 位数字的两个未装箱字三元组添加到新的未装箱字三元组中 并且还返回任何溢出 LANGUAGE MagicHash LANGUAGE UnboxedTuples import GHC Prim plusWord2 Wo
  • 函数式编程是否需要新的命名约定?

    我最近开始使用 Haskell 学习函数式编程 并在 Haskell 官方 wiki 上发现了这篇文章 如何阅读哈斯克尔 http www haskell org haskellwiki How to read Haskell What t
  • 显示未定义的实例

    可以采取任何措施来为未定义的值定义 Show 实例吗 也许存在一些 GHC 扩展 我想要这样的东西 gt print 1 undefined 1 undefined 根据Haskell 2010 报告 第 9 章 http www hask
  • Haskell/GHC:使用相同模式匹配多个一元构造函数

    所以我正在尝试定义 TrieSet 数据类型 尽管我知道我不需要 http hackage haskell org package TrieMap module Temp where import Data Map data TrieSet
  • Haskell 中函数和函子有什么区别?只有定义吗?

    在 Haskell 中 当编写函数时 这意味着我们将某个东西 输入 映射到另一个东西 输出 我尝试 LYAH 来理解 Functor 的定义 看起来和普通 Functor 一样 函数被称为函子有什么限制吗 Functor 是否允许有 I O
  • 预期设备类型为 cuda 的对象,但在 Pytorch 中获得了设备类型 cpu

    我有以下计算损失函数的代码 class MSE loss nn Module metric L1 L2 norms or cosine similarity mode training or evaluation mode def init
  • 在 C# 中实现记忆化 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我知道这个话题 记忆 已经被讨论了很多 比如here https stackoverflow com questions 285216
  • 如何使用类中的常量作为 php 函数中的参数定义?

    我有一堂课 class FetchMode const FetchAll 0 const FetchOne 1 const FetchRow 2 和一个函数 function getRecordSet FetchMode FetchMode
  • Mootools 使用“extend”方法扩展“Function”类,导致 jQuery 无法使用

    Mootools 扩展了 Function 类 并在其中添加了一个名为 extend 的新方法 现在 jQuery 尝试使用 jQuery prototype extend 添加 扩展 功能 然而 由于 extend 已经是 jQuery
  • 如何在 PHP 中检查特定类型的对象

    我有一种方法 它接受 PDO 对象作为参数 允许用户使用现有连接 而不是打开新连接的方法 并节省资源 public static function databaseConnect pdo null 我知道is object 检查参数是否是一
  • 为什么 'self.self' 在 swift 中编译并运行?

    昨天我回顾了 Swift 中的一段代码 其中包括这一行 self self someProperty 这让我很惊讶 因为这个词self被保留并用作对当前实例的引用 起初我用其他语言检查了这种现象 但都给出了错误 这并不奇怪 但是 为什么它能
  • Haskell Cabal 包 - 找不到 Paths_ 模块

    我正在开发一个 Haskell 项目 Happstack 服务器 Blaze HTML 前端作为主要库 我想添加一个静态数据目录 看起来你可以使用 Cabal 使用自动生成的Path
  • OCaml 作为 C 库,hello world 示例

    我希望通过 C 调用 OCaml 代码 方法是将 OCaml 编译为包含 C 接口的静态或共享库 这一页 https caml inria fr pub docs manual ocaml intfc html似乎解释了如何为 OCaml
  • 依赖注入系统中的事件朝哪个方向发展?

    上或下 我是一个非常注重视觉的人 我将我的应用程序视为一个层次结构 顶部是根 底部是叶子 我还了解到 在 DI 系统中 容器不知道其所包含对象的职责 功能 相反 所包含的对象知道它们的上下文 因为上下文 依赖项 被注入 UP 非 DI 方式

随机推荐

  • 自动替换在 emacs 中输入的某些文本字符串

    有一个小细节一直困扰着我一段时间 即我经常打字 inclued代替 include 如果不是很明显的话 我编写了大量 C 和 C 程序 这个拼写错误破坏了无数的构建并消耗了本来可以用来喝咖啡或冲浪的时间 当然 emacs 可以提供帮助并在我
  • 当 ExceptionMapper 创建响应时,未遍历 RestEasy 后处理拦截器链

    我正在使用 RestEasy 构建我的 Restful Web 服务 我已经实现了 ExceptionMappers 来准备特定的异常响应 我还实现了 MessageBodyWriterInterceptors 和几个 PostProces
  • EasyMock的使用方法

    期望似乎对我不起作用 package com jjs caf library client drafting import static org junit Assert import org easymock EasyMock impor
  • 用于从段落中删除所有属性的正则表达式

    我知道正则表达式通常不应该用于解析 html 内容 在我的特殊情况下 我需要它们 原因是 我使用 rte 编辑器 并且在粘贴到编辑器中时需要对段落属性进行一些替换 我有类似的东西 p text blah blah p 我需要删除所有属性 以
  • 数组中的clear方法

    我正在尝试创建一个清除方法来清除我拥有的数组 我已经看到使用清除方法是我所需要的 但我似乎无法使用它 list clear 我认为我必须做的 public void clear return doctors clear 顺便说一下 医生是一
  • 参数和属性之间的区别[重复]

    这个问题在这里已经有答案了 可能的重复 getAttribute 和 getParameter 之间的区别 https stackoverflow com questions 5243754 difference between getat
  • 当我的 MySQL 表更新时,如何收到电子邮件?

    您好 我想知道 MySQL 中是否有一种方法可以在 MySQL 表中添加一行时自动向自己发送电子邮件 实现这一目标的最佳方法是使用触发器和 cron 创建一个 通知队列 表 并在将行插入所需表时使用触发器填充该表 eg CREATE TAB
  • 如何在 R 中创建类似箱线图的分类散点图?

    有谁知道如何创建散点图R创建像这样的情节these http graphpad com support faq graph tip how can i make a barcolumn graph that also shows the i
  • 使用 zip4j 重命名 zip 中的文件

    我在用着zip4j http www lingala net zip4j download php1 3 1 在我的应用程序中压缩文件 现在我尝试重命名 zip 内的文件 而不必重命名文件本身 似乎有一种方法可以做到这一点 但它不起作用 我
  • 将当前日期设置为在 Bootstrap 日期选择器中选择

    我在用引导日期选择器 https github com eternicode bootstrap datepicker在我的代码中 如何在 JavaScript 中选择当前日期并将其显示为已选择 经过研究 这是我正在使用的代码 但当天没有显
  • 本地 JS 文件的 Typescript 声明文件

    当我们正在转换为 Typescript 的过程中 我正在尝试为工作中的 Javascript 文件添加类型 但是 我无法识别声明文件 这是我的文件结构 js Foo js typings Foo 索引 d ts index ts 包 jso
  • Symfony 4:JWT 和 Behat 的测试数据库

    我将 API Platform 2 1 与 Symfony 4 结合使用 并使用 LexikJWTAuthenticationBundle 进行身份验证 并使用 Behat 进行测试 我无法正确设置 这是到目前为止我的配置 Feature
  • 将使用 FPDF php 库创建的 PDF 保存在 MySQL blob 字段中

    我需要创建一个 pdf 文件fpdf http www fpdf org库并将其保存在我的 MySQL 数据库的 blob 字段中 问题是 当我尝试从 blob 字段检索文件并将其发送到浏览器进行下载时 下载的文件已损坏并且无法正确显示 如
  • 列出本地打印机

    我使用此例程列出计算机上安装的本地打印机 var p pointer hpi PRINTER INFO 2A hGlobal cardinal dwNeeded dwReturned DWORD bFlag boolean i dword
  • 是否有一个库可以将 java 命令行选项解析为关联数组?

    我需要一个可以采用以下形式的命令行选项的库java jar aaa a bbb b ccc c并返回一个数组 其值可以通过以下方式访问argsArray aaa argsArray bbb etc 有一些带有示例的库可以做到这一点吗 Jav
  • Lucene 上打开的文件太多错误

    我正在进行的项目是对一定数量的数据 长文本 建立索引 并将它们与每个时间间隔 大约 15 到 30 分钟 的单词列表进行比较 一段时间后 比如说第 35 轮 在开始索引第 36 轮的新数据集时 发生了此错误 ERROR 2011 06 01
  • 在 data.frame 中有效地定位分组常量列

    如何有效地从数据框中提取分组常量列 我在下面包含了一个 plyr 实现 以精确说明我想要做的事情 但它很慢 我怎样才能尽可能高效地做到这一点 理想情况下根本不分割数据框 base lt data frame group 1 1000 a s
  • 处理第三方API时正确的系统设计是什么?

    This 博客文章 http blog njoubert com 2010 12 structuring iphone apps design principles html朱伯特刚刚睁开了我的眼睛 我接触过很多 Java 和其他语言的设计
  • 比较字符串和整数会产生奇怪的结果

    我真的很困惑为什么这个操作有效 有人可以解释一下吗 test1 d85d1d81b25614a3504a3d5601a9cb2e test2 3581169b064f71be1630b321d3ca318f if test1 0 echo
  • 如何在 Haskell 中建模类层次结构?

    我是一名 C 开发人员 来自面向对象的世界 我从接口 类和类型层次结构的角度开始思考 由于 Haskell 缺乏面向对象 有时我发现自己陷入困境 无法想出用 Haskell 建模某些问题的方法 如何在 Haskell 中对涉及类层次结构的现