如何“newtype”IntSet?

2024-02-25

谢谢newtypeGeneralizedNewtypeDeriving扩展,我们可以毫不费力地定义不同的轻量级类型:

newtype PersonId = PersonId Int deriving (Eq, Ord, Show, NFData, ...)
newtype GroupId  = GroupId Int deriving (Eq, Ord, Show, NFData, ...)

这允许类型系统确保PersonId不是偶然使用的GroupId符合预期,但仍然继承选定的类型类实例Int.

现在我们可以简单地定义PersonIdSet and GroupIdSet as

import Data.Set (Set)
import qualified Data.Set as Set

type PersonIdSet = Set PersonId
type GroupIdSet  = Set GroupId

noGroups :: GroupIdSet
noGroups = Set.empty

-- should not type-check
foo = PersonId 123 `Set.member` noGroups

-- should type-check
bar = GroupId 123 `Set.member` noGroups

这是类型安全的,因为映射是由键类型参数化的,而且,Set.member操作是多态的,所以我不需要定义每个 id 类型的变体,例如personIdSetMember and groupIdSetMember(以及我可能想要使用的所有其他设置操作)

...但是我怎样才能使用更有效的IntSets 代替PersonIdSet and GroupIdSet分别以与上面示例类似的方式?有没有一种简单的方法,无需将整个 Data.In Rest API 包装/复制为类型类?


我认为你必须包裹IntSet如你所说。但是,您可以引入幻像类型来创建一系列 ID 类型,而不是单独定义每个 ID 类型。IDs and IDSet彼此兼容的:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import qualified Data.IntSet as IntSet
import Data.IntSet (IntSet)

newtype ID a = ID { unID :: Int }
              deriving ( Eq, Ord, Show, Num )

newtype IDSet a = IDSet { unIDSet :: IntSet }
              deriving ( Eq, Ord, Show )

null :: IDSet a -> Bool
null = IntSet.null . unIDSet

member :: ID a -> IDSet a -> Bool
member i = IntSet.member (unID i) . unIDSet

empty :: IDSet a
empty = IDSet $ IntSet.empty

singleton :: ID a -> IDSet a
singleton = IDSet . IntSet.singleton . unID

insert :: ID a -> IDSet a -> IDSet a
insert i = IDSet . IntSet.insert (unID i) . unIDSet

delete :: ID a -> IDSet a -> IDSet a
delete i = IDSet . IntSet.delete (unID i) . unIDSet

所以,假设你有一个Person类型,和一个Group输入,你可以这样做:

type PersonID = ID Person
type PersonIDSet = IDSet Person

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

如何“newtype”IntSet? 的相关文章

  • 在 Haskell 中为自定义数据类型创建 Read 类型类的实例

    我有一个自定义数据类型Foo Foo a Int b Int 我正在尝试使 Foo 成为 read 的自定义实例 我已经有一个功能了bar String gt Foo我尝试这样做 instance Read Foo a b where re
  • 如何在 Kotlin 中正确处理大于 127 的 Byte 值?

    假设我有一个带有变量的 Kotlin 程序b类型的Byte 外部系统向其中写入大于的值127 外部 意味着我无法更改它返回的值的类型 val a Int 128 val b Byte a toByte Both a toByte and b
  • Haskell,范围缩小到无步骤[重复]

    这个问题在这里已经有答案了 为什么在 Haskell 中工作范围不能降低到没有步骤 7 1 gt 但只工作这个 7 6 1 gt 7 6 5 4 3 2 1 Haskell 无法知道您想要执行 1 除非您给出提示 在某些情况下 您可能需要一
  • 算法 - 如何有效删除列表中的重复元素?

    有一个list L 它包含以下元素任意类型each 如何有效删除此类列表中的所有重复元素 必须保留订单 只需要一个算法 因此不允许导入任何外部库 相关问题 在Python中 从列表中删除重复项以使所有元素都是唯一的最快算法是什么在维持秩序的
  • 表达式“ap zip tail”如何工作

    我想知道怎么写f x zip x tail x 点免费 所以我使用了pointfree程序 结果是f ap zip tail ap作为 Control Monad 的函数 我不明白点自由定义是如何工作的 如果我能从类型的角度去理解的话 希望
  • 如何指定 sbcl(或 common lisp)向量中的元素类型?

    我尝试在 sbcl 1 1 14 中执行以下代码 但类型检查似乎忽略了向量元素的声明 defun test vec declare type vector integer vec format nil a elt vec 0 有什么提示吗
  • 我可以让 C 函数返回任意类型吗?

    我编写了一个解释串行数据 CAN 的函数 当前返回一个浮点数 我希望该函数包含一个参数 其中用户在字符串中指定返回类型 并且该函数返回该类型的值 这只是一个方便的事情 以避免编写共享几乎所有相同代码的多个函数 将 void 指针传递给您想要
  • Java长到MySQL

    Java相当于什么long在 MySQL 的上下文中数据类型 SIGNED BIGINT http dev mysql com doc refman 5 0 en numeric types html是一个 8 字节长的整数 就像 Java
  • “反向”使用 Maybe Monad

    假设我有很多功能 f a gt Maybe a g a gt Maybe a h a gt Maybe a 我想按以下方式组合它们 如果 f 返回 Nothing 则计算 g 如果 g 返回 Nothing 则计算 h 如果其中任何一个计算
  • 是否可以在 .NET 中编写仅接受数字类型的通用函数?

    假设我想编写一个如下所示的函数 像往常一样 一个简单的示例用于说明目的 Public Function calcSqSum Of T ByVal list As IEnumerable Of T As T Dim sumSq As T Fo
  • 是否有一个基于对象身份的、线程安全的记忆库?

    我知道记忆化似乎是堆栈溢出的 haskell 标签上的一个长期话题 但我think以前没有人问过这个问题 我知道 Haskell 有几个不同的 现成 记忆库 memo combinators 和 memotrie 包 利用涉及惰性无限数据结
  • 处理许多不相关的类型时避免样板

    我正在编写处理以下值的代码语言 扩展 注释 语法 http hackage haskell org packages archive haskell src exts 1 1 4 doc html Language Haskell Exts
  • Haskell 测量函数性能

    在 Haskell 中 我如何 简单地 测量函数的性能 例如 运行需要多长时间 或者需要多少内存 我知道分析 但是 是否有一种更简单的方法不需要我对代码进行太多更改 测量运行需要多长时间以及需要多少内存是两个独立的问题 即 基准测试和分析
  • Haskell 错误处理方法

    毫无疑问 Haskell 中有多种机制来处理错误并正确处理它们 错误单子 要么 也许 异常等 那么为什么用其他语言编写容易出现异常的代码比用 Haskell 感觉更简单呢 假设我想编写一个命令行工具来处理命令行上传递的文件 我想 验证提供的
  • 为什么 enumerate、zip、range 类型不属于 types.GeneratorType?

    Python 3 引入了类似生成器的对象 在调用时返回range and zip 返回的对象就像一个生成器 可以迭代一次 但不能很好地 打印 就像enumerate 返回参数 然而 我很困惑地发现它们是不同的对象类型并且不属于types G
  • 有没有办法在 Emacs 中使用 Djinn 自动生成 Haskell 代码?

    标题几乎说明了一切 我正在寻找这样的东西 f Int gt Bool gt Int f body Djinn 可以使用定理证明来通过证明该类型存在来生成此类函数的代码 我想知道 是否有现有的方法可以从 Emacs 中获取此功能 因此 我不需
  • 如何处理在组合下发生变化的类型?

    我最近读了一篇非常有趣的论文单调性类型 https infoscience epfl ch record 231867 files monotonicity types pdf其中描述了一种新的 HM 语言 该语言可以跟踪操作之间的单调性
  • Haskell 和 Idris 之间的区别:类型宇宙中运行时/编译时的反映

    因此 在 Idris 中 编写以下内容是完全有效的 item b Bool gt if b then Nat else List Nat item True 42 item False 1 2 3 cf https www youtube
  • 在Python中检测re(regexp)对象

    我想知道什么是正确的 pythonic 向后和向前兼容的方法如何检查对象是否已编译re object isinstance方法不能轻易使用 而生成的对象声称是 sre SRE Pattern object gt gt gt import r
  • 为什么 Go 中只有 int 而没有 float?

    在 Go 中 有这样的类型int这可能相当于int32 or int64取决于系统架构 我可以声明一个整数变量而不用担心它的大小 var x int 为什么没有这个类型float 这相当于float32 or float64取决于我的系统架

随机推荐