类型类与代数数据类型?

2024-01-03

我经常开始考虑要定义的类型类方面的问题,并意识到当我开始编码时我不需要类型类,并且可以使用代数数据类型来解决我的问题,这看起来更简单。因此,我想知道什么时候需要类型类。

据我了解,类型类是表示某些类型存在某些函数的一种方式。例如,当类型 MyType 是 Monoid 的实例时,我可以使用以下函数mempty :: MyType and mappend :: MyType -> MyType -> MyType,使得幺半群定律成立。

通过将 Monoid 定义为类型而不是类型类,我们可以使用代数数据类型实现相同的效果:

data Monoid a = Monoid { mempty :: a
                       , mappend :: a -> a -> a}

然后通过定义类型的新值来说类型 MyType 是一个幺半群Monoid MyType(对于类型类,这是通过将其声明为实例来完成的):

monoidMyType :: Monoid MyType
monoidMyType = Monoid { mempty = ...
                      , mappend = \a b -> ... }

然后,我们可以编写对幺半群进行操作的函数,例如:

dummyFun :: Monoid a -> a -> a
dummyFun m x = mempty m x

并通过显式传递适当的“幺半群值”来使用这些函数:

result = dummyFun monoidMyType valueOfMyType

对于类型类,等效的最后两个步骤将非常相似地发生:

dummyFun :: (Monoid a) => a -> a
dummyFun x = mempty x

result = dummyFun valueOfMyType

我看到的唯一实质性区别是,对于代数数据类型,当我们调用函数时必须显式传递幺半群值dummyFun。虽然不必明确通过它更实际一些,但在我看来这并不是一个主要障碍。

事实上,我看到代数数据类型相对于类型类的一个优势:您可以将不同函数中的类型关联在一起:

data Bla a b = Bla {f1 :: a -> b, f2 :: b -> a, ...}

使用类型类执行此操作(我相信)需要使用多参数类型类扩展。

有没有理由使用我在这里没有看到的类型类?

在设计软件时,您是否可以交替选择使用类型类或代数数据类型,或者是否存在不能没有类型类的情况?


您刚刚发明了类型类!一类is函数字典。在编译过程中,代码如下

class Monoid a where
    mempty :: a
    mappend :: a -> a -> a

instance Monoid [a] where
    mempty = []
    mappend = (++)

mconcat :: Monoid a => [a] -> a
mconcat = foldr mappend

main = print $ mconcat ["foo", "bar"]

被翻译成明确的字典传递风格。

data Monoid a = Monoid { mempty :: a, mappend :: a -> a -> a }

list_monoid = Monoid [] (++)

mconcat :: Monoid a -> [a] -> a
mconcat monoid = foldr (mappend monoid)

main = print $ mconcat list_monoid ["foo", "bar"]

这种翻译正是类型类和字典之间最重要的区别:类是隐式的。您不必显式传递monoid变量周围 - 编译器会为您处理管道问题。构建像这样的组合实例会特别乏味Ord a => Ord [a]用手。

类和字典之间还有一个关键区别,那就是连贯性。基本上,总是最多有一个“最佳”实例来满足给定的约束,该实例是全局且唯一的,并且您无法覆盖它。另一方面,使用字典传递样式,该函数将仅使用您传入的任何字典,并且不保证唯一性。这有时是好的,有时是坏的 https://www.youtube.com/watch?v=hIZxTQP1ifo.

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

类型类与代数数据类型? 的相关文章

  • 为自定义镜头编写类别实例

    我一直在读这个article http www haskellforall com 2012 01 haskell for mainstream programmers 28 html用于理解镜头 我知道这不同于 爱德华 克内特 Edwar
  • 如何在递归方案中派生实例

    我正在测试其中的一些想法本文 http blog sumtypeofway com an introduction to recursion schemes 我想派生 Term 类型的 Eq 实例 LANGUAGE DeriveFuncto
  • 镜头中的观看和使用有什么区别?

    有什么区别 view MonadReader s m gt Getting a s a gt m a and use MonadState s m gt Getting a s a gt m a in 控制镜头吸气剂 https hacka
  • Haskell:如何创建将函数应用于元组项的最通用函数

    这是一个个人练习 旨在更好地理解 Haskell 类型系统的局限性 我想创建最通用的函数 将某些函数应用于 2 条目元组中的每个条目 例如 applyToTuple fn a b fn a fn b 我试图让这个函数在以下每种情况下都起作用
  • yesod——密码保护临时站点

    我正在尝试设置 yesod 网络服务器的临时实例 我想知道是否有一些简单的方法可以使整个站点受到密码保护 具体来说 我希望能够提示那些导航到我的网站的人提供凭据 经过身份验证后 它应该像典型站点一样运行 但如果他们无法验证自己的身份 他们就
  • 在 Haskell 中对单位的组成(例如英寸、美元等)进行建模

    跟进自我之前的一个问题 https stackoverflow com q 73375273 222529 我问如何创建一个可以对单元进行建模的类型 例如Inch 作为 Haskell 中的一种类型 我现在面临的问题是如何对该单元和其他单元
  • 在 Haskell 中为自定义数据类型创建 Read 类型类的实例

    我有一个自定义数据类型Foo Foo a Int b Int 我正在尝试使 Foo 成为 read 的自定义实例 我已经有一个功能了bar String gt Foo我尝试这样做 instance Read Foo a b where re
  • 无法通过 cabal 安装“System.Random”

    我尝试通过 Cabal 通过 Powershell 和 Git Bash 安装 System Random 得到这个结果 PS C Users xxx gt cabal install random Resolving dependenci
  • Haskell 中的常量变量声明

    要声明常量变量 我可以在 Ruby 中执行以下操作 class COLOR RED 10 BLUE 20 GREEM 30 end COLOR RED回报10 COLOR BLUE回报20 等等 我如何在 Haskell 中实现这一点 我想
  • 为什么haskell中的递归列表这么慢?

    我对 Haskell 很陌生 我在 Haskell 中定义了一个函数 febs Integral a gt a gt a febs n n lt 0 0 n 1 1 n 2 1 otherwise febs n 1 febs n 2 但是
  • 是否有一个基于对象身份的、线程安全的记忆库?

    我知道记忆化似乎是堆栈溢出的 haskell 标签上的一个长期话题 但我think以前没有人问过这个问题 我知道 Haskell 有几个不同的 现成 记忆库 memo combinators 和 memotrie 包 利用涉及惰性无限数据结
  • 将 Either 列表转换为其中包含列表的 Either 列表

    我是 Haskell 的初学者 我正在编写一些使用 Haskell 的代码Either https hackage haskell org package base 4 9 0 0 docs Data Either html用于错误处理 E
  • GHC 是否使用存在类型的动态调度?

    下面的代码是否使用了 C 或 Java 中所理解的动态调度 据我了解 在最后一行 编译器不可能在编译时知道要调用哪个 实现 但代码会编译并产生正确的结果 有人可以解释一下 这背后有什么样的实现 例如 vptr 吗 LANGUAGE Exis
  • Haskell 中的相互递归求值器

    Update 我已经添加一个答案 https stackoverflow com questions 3524485 mutually recursive evaluator in haskell 4504200 4504200这描述了我的
  • 反应性香蕉时间延迟

    我已经查阅了文档反应香蕉 http hackage haskell org package reactive banana 而且我找不到指定明确时间延迟的方法 举例来说 我想采取Event t a并将其所有发生的事件移至未来 1 秒 或获取
  • Haskell 错误处理方法

    毫无疑问 Haskell 中有多种机制来处理错误并正确处理它们 错误单子 要么 也许 异常等 那么为什么用其他语言编写容易出现异常的代码比用 Haskell 感觉更简单呢 假设我想编写一个命令行工具来处理命令行上传递的文件 我想 验证提供的
  • 如何处理在组合下发生变化的类型?

    我最近读了一篇非常有趣的论文单调性类型 https infoscience epfl ch record 231867 files monotonicity types pdf其中描述了一种新的 HM 语言 该语言可以跟踪操作之间的单调性
  • Haskell 排列库函数 - 请澄清一下?

    这是代码permutationsHaskell 中的函数Data List module permutations a gt a permutations xs0 xs0 perms xs0 where perms perms t ts i
  • 为什么解析器组合器“seq”用“bind”和“return”定义?

    我正在读这个article http eprints nottingham ac uk 237 1 monparsing pdf关于解析器组合器并且不理解以下内容 他们说使用seq 见下文 导致解析器将嵌套元组作为结果 操作起来很混乱 se
  • 如何避免编写这种类型的 Haskell 样板代码

    我经常遇到这种情况 这很烦人 假设我有一个 sum 类型 它可以保存一个实例x或一堆其他无关的事情x data Foo x X x Y Int Z String other constructors not involving x 要声明

随机推荐

  • mscorlib.dll 中发生了“System.ArgumentOutOfRangeException”类型的第一次机会异常

    我是 C 客户端和服务器应用程序的新手 正在开发文件上传客户端和服务器应用程序 我可以从客户端应用程序成功地将文件名和文件数据上传到服务器 但是当我尝试实现一个新的文本框 允许文件上传客户端输入他 她的姓名 并在他 她单击发送按钮时将信息与
  • 并行动态规划

    有没有讨论如何采用动态程序并将其并行化的好论文 我们最近发表了一篇论文 展示了如何通过共享无锁哈希表在共享内存多核计算机上并行化任何动态编程 Stivala A 和 Stuckey P J 和 Garcia de la Banda M 和
  • 使用 bazel 覆盖率生成 lcov 覆盖率文件时,未创建输出“_coverage/_coverage_report.dat”

    我正在使用 bazel 来管理我们的 golang 项目 我在网上找到了一个选项 我可以通过先生成 lcovcoverage dat 文件来生成覆盖率 html 文件 然后使用 genhtml 生成 html 然而 我却无法成功迈出第一步
  • 确定单元格是否通过 Excel 中的 VBA 链接到查询表

    我使用 QueryTables 将 Excel 工作表链接到数据源 效果很好 我想引入逻辑来检查给定单元格并确定该单元格是否是现有查询表的左上角 这在概念上似乎微不足道 但在实践中却被证明是难以捉摸的 如果我尝试检查与 QueryTable
  • 安卓。警报管理器在奇怪的时间触发

    我使用以下代码设置重复闹钟 每 5 分钟一次 public void SetAlarm Context context AlarmManager am AlarmManager context getSystemService Contex
  • 将列更改为默认 SYSDATE 的 DATE 的 SQL 语句(Oracle)是什么?

    我得到了一个表名 kundorder 和列名称 datum 我想将数据类型更改为 DATE SYSDATE 但我无法让它工作 我认为它应该看起来像这样 ALTER TABLE kundorder MODIFY datum DATE DEFA
  • 在 iFrame 中使用 Google 云端硬盘不起作用

    我在 iFrame 中使用 Google Drive 时遇到了一些问题 通常 在 iFrame 中使用它无论如何都不是一个好主意 但这是为了教学 Google Drive 学生可以编写一些代码 然后他们可以预览它 预览需要在 iFrame
  • 在 Uint8Array 中搜索多字节模式

    我有一个 nodejs 脚本 我想在其中解析 MP3 帧 这些帧很容易检测 因为每个帧都以两个字节开头0xff 0xfb 我正在使用一个Uint8Array访问该文件的字节 使用 indexOf call data 0xff 我可以轻松搜索
  • IE 中的 Google Maps API v3 不显示地图或标记

    我们最近从 Google 地图 v2 升级到 v3 现在标记和地图将不会在任何版本的 IE 中显示 它适用于所有其他浏览器 控制台显示 Stack Overflow 错误 我们认为这与标记和 或标记的创建有关 我们禁用了 fitbounds
  • Numpy where 返回空数组

    我有一个数组 例如 a 5 1 3 0 2 我应用 where 函数 np where a 2 输出是一个空数组 array dtype int64 我发现了同样的问题here https stackoverflow com questio
  • Visual Studio 2015 - 连接到 Visual Studio 库进行扩展和更新时出现 Visual Studio 库错误

    当尝试从扩展和更新获取 Visual Studio 扩展时 我收到以下错误 向 Visualstudiogallery msdn microsoft com Services VStudio Extension svc 发出 HTTP 请求
  • 如何在单文件组件中使用 VueJS 2 全局组件?

    我正在尝试使用全局注册的组件 带有Vue 组件 在单个文件组件中但我总是得到 vue common js 2611 Vue warn Unknown custom element
  • 如何使用 System.Text.Json 将 double[] 二维数组序列化为 JSON?

    我需要写一个double 使用 System Text Json 转换为 JSON 文件 但此序列化程序不支持二维数组 我需要一些帮助来转换我的double to a List
  • PyPy 中的 GIL 在哪里?

    PyPy GIL 是 RPython 中 PyPy 解释器实现的一部分 还是 translate py 自动添加的东西 也就是说 如果我用 RPython 编写自己的新语言解释器并通过 translate py 运行它 它是否会先验地受到
  • 如何向网页添加自定义右键菜单?

    我想向我的 Web 应用程序添加自定义右键菜单 可以在不使用任何预构建库的情况下完成此操作吗 如果是这样 如何显示一个不使用第 3 方 JavaScript 库的简单自定义右键菜单 我的目标是像 Google Docs 那样 它允许用户右键
  • 提示用户从 Dropbox 下载时保存

    我想要一个从 Dropbox 下载文件的链接 该链接会提示用户而不是在浏览器中显示该文件 这可能需要将内容处置标头设置为 附件 我目前正在使用 Dropbox 媒体 URL 如下所述 https www dropbox com develo
  • C2039:类不是命名空间的成员

    法师 接口 Context h pragma once include
  • onResume 手机屏幕锁定时被反复呼叫

    看来 如果手机屏幕锁定时某个 Activity 位于前台 广播事件和 或唤醒锁将导致该 Activity 的 onResume 被调用 无论它们是否适用于您的应用程序 即使您不以任何方式与手机交互 也会发生这种情况 不解锁它 不触摸它 不做
  • Android 上的 SQLite 数据库有大小限制吗? [复制]

    这个问题在这里已经有答案了 我想将 db 文件内部存储在设备 SD 卡中 并希望从中访问数据 有人可以告诉我们在我们的 Android 应用程序中可以检索的 db 文件的最大大小吗 没有任何内存异常 SQLite 的最大大小为 10MB 到
  • 类型类与代数数据类型?

    我经常开始考虑要定义的类型类方面的问题 并意识到当我开始编码时我不需要类型类 并且可以使用代数数据类型来解决我的问题 这看起来更简单 因此 我想知道什么时候需要类型类 据我了解 类型类是表示某些类型存在某些函数的一种方式 例如 当类型 My