属于两种不同类型的一个值构造函数

2024-01-03

假设我有三个值构造函数:

A { a :: Int }
B { b :: Char }
C { c :: Bool }

我想创建两种类型X and Y这样类型的值X可以是一个A, B or C,像这样:

data X = A {...} | B {...} | C {...}

和类型的值Y只能是一个A or B,像这样:

data Y = A {...} | B {...}

这样我就可以编写如下代码:

foo :: X -> Int -- can pattern match
foo (A _) = 1
foo (B _) = 2
foo (C _) = 3
bar :: Y -> Bool -- also can pattern match with the same constructors
bar (A _) = true
bar (B _) = false
baz = A 1 -- baz is inferred to be a type that can fit in both X and Y

我知道我可以将构造函数包装在以下定义中X and Y像这样:

data X = XA A | XB B | XC C
data Y = YA A | YB B

但这似乎不整洁(必须输入XA A等等)。我可以扩展内容A, B, and C的定义X and Y, but A等等非常复杂,我不想重复定义。

这对于 Haskell(包括任何 GHC 扩展)来说可能吗?

Edit

GADT 似乎可以按要求回答我的问题(因此我将散热器的答案标记为正确),但仍然不够灵活以满足我的需要。例如,据我所知,你不能这样做:

func1 :: [XY Y_] -- returns a list of items that can only be A or B
func1 = ...
func2 = func1 ++ [C True] -- adding a C item to the list

func2应输入为[XY X_],但这在 Haskell 中是不可能的(除非我的实验是错误的)。

经过更多的网络搜索后,我真正想要的是 OCaml 的多态变体(据我所知)仅存在于 OCaml 中(着眼于更“实用”而不是“学术”语言)。

Edit 2

请参阅 comonad 的回答。看起来确实可以做到,但是我觉得这个问题最好不要重写太多次。 :-)


类型类,如jetxee https://stackoverflow.com/questions/4256502/one-value-constructor-belonging-to-two-different-types/4256813#4256813所描述的,可能是适当的方法。

如果您还希望能够进行模式匹配和使用构造函数,那么您可以使用 GADT 和空数据声明来定义一种数据类型中的所有构造函数。如果采用这种方法,所有构造函数都将是同一数据类型的成员,同时允许您将域限制为仅构造函数的子集。

data X_
data Y_
data XY a where
  A :: Int -> XY a
  B :: Char -> XY a
  C :: Bool -> XY X_
type X = XY X_ -- Contains values built with constructors A, B, and C 
type Y = XY Y_ -- Contains only values built with constructors A and B

现在一个函数只使用A and B适用于两种类型X and Y。一个函数使用C仅适用于类型X.

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

属于两种不同类型的一个值构造函数 的相关文章

  • Python 检查整数输入

    我试图允许用户输入我的程序 但是当他们输入字符串时我的程序失败 这是一个更大的程序 但正在尝试纠正问题 到目前为止我已经 data raw input Enter a number number eval data if type numb
  • 为什么 Haskell (Hugs) 中的 Show 实例会导致堆栈溢出错误?

    下面是 Haskell 中的多态数据类型 由 Hugs 解释 我正在尝试创建一个 Show for Equality 的实例 实例声明表示 如果类型 a 在 Show 中 则相等 a 在 Show 中 它应该以 a b 的形式打印构造函数
  • fgetc 无法识别 EOF [重复]

    这个问题在这里已经有答案了 下面的程序在各种 Solaris Linux 版本上运行良好 但在 AIX 上运行不佳 但是 如果我更换while c EOF with while c 0xff 在 AIX 上它运行得很好 有什么想法吗 我检查
  • 不明白这个 haskell 代码中的内容

    我有一些 Haskell 代码 我正在尝试完成它 但我不明白其中发生了什么 type Bag a a gt Int emptyB Bag a emptyB e gt 0 countB Eq a gt Bag a gt a gt Int co
  • haskell复制目录的方法是什么

    我发现自己用 Haskell 编写越来越多的脚本 但在某些情况下 我真的不确定如何 正确 地做到这一点 例如递归地复制目录 a la unixcp r 由于我主要使用 Linux 和 Mac OS 所以我通常会作弊 import Syste
  • enumFromTo 如何工作?

    我无法将号码添加到Char 以下内容将无法编译 a 1 但是 a z 成功创建一个字符串 其中每个字符值都会递增 有没有一个特殊的函数可以增加Char 我知道我能做到chr ord c 1 如何 a z 或底层enumFromTo函数增加结
  • Coq:Type(n) 中的 Prop 与 Set

    我想考虑以下三个 相关的 Coq 定义 Inductive nat1 Prop z1 nat1 s1 nat1 gt nat1 Inductive nat2 Set z2 nat2 s2 nat2 gt nat2 Inductive nat
  • 使用 GHC.Generics 恢复类型定义

    昨天我尝试回答这个问题是关于数据类型的表示 https stackoverflow com questions 22715572 a serializable representation of a data type for client
  • PHP instanceof 对于 true 条件返回 false

    我完全困惑为什么 php 的instanceof当以下情况时 运算符坚持认为此处的 LVALUE 不是已定义类的实例get class说是的 class WhereIn public function construct args echo
  • 无法让 wxHaskell 在 Mac 上从 ghci 工作

    我正在尝试跑步一个例子 http www haskell org haskellwiki WxHaskell Quick start Hello world in wxHaskell using EnableGUI function htt
  • 记录语法和求和类型

    我有关于 Haskell 中的总和类型的问题 我想创建一个由两个或多个其他类型组成的总和类型 并且每个类型可能包含多个字段 一个简单的例子是这样的 data T3 T1 a Int b Float T2 x Char deriving Sh
  • Pandas 报告系列为小数时为对象

    我需要一种自动可靠的方法来查找 pandas 数据框中每列的数据类型 我一直在使用 dtype 但注意到它有一些意想不到的东西 考虑这个 10 行数据框 df a Out 6 0 250 00 1 750 00 2 0 00 3 0 00
  • 优化计算 200 万以下所有素数总和的 Haskell 代码

    欧拉计划中的问题 10 我在那里看到了一些讨论 但仅限于 C 我用下面的代码来计算 print sum sieve 2 2000000 where sieve sieve x xs x sieve filter 0 mod x xs 需要很
  • “==”对象相等的标准定义是什么?

    There seems与普遍理解之间的不匹配 以及它的实际作用 给出这个问题的一些背景 typeof new Number 1 returns object typeof new String 1 returns object typeof
  • Haskell 中的随机枢轴快速排序

    是否有可能在 Haskell 中实现快速排序 使用 RANDOM PIVOT 但仍然有一个简单的Ord a gt a gt a 签名 我开始了解 Monad 目前 我将 monad 解释为某种 命令模式 这对于 IO 非常有用 所以 我知道
  • Haskell - 让函数返回空字符

    我正在尝试创建一个函数来删除字符串中的每个第 n 个元素 dropEvery String gt Int gt String dropEvery str n map char indx gt if indx mod n 0 then cha
  • 数据记录的类约束

    我有一个data type data BuildException a KillBuild JobID a Stage FailBuild JobID a Stage CancelBuild JobID a Stage StopBuild
  • 如何编写将布尔值返回到一个函数的函数

    我在这里发现了一个类似的问题 它问了几乎相同的问题 但又不完全一样 我的问题是如何将 a gt Bool 类型的函数列表组合成一个也是 a gt Bool 的函数 Ex compose a gt Bool gt a gt Bool comp
  • Haskell 程序查找列表中元素的位置

    我需要编写一个函数来查找列表中一个特定元素的位置 我是这样写的 findPos list elt list 1 head list elt 0 otherwise 1 findPos tail list elt 但是如果列表中元素重复怎么办
  • 如何在 Haskell 中处理这个简单的 IO 异常

    全部处理 在下面的代码中 getDirectoryContents dir可能会失败 例如dir可能不存在 如何捕获这个并向用户抛出有意义的消息 我知道 IO 异常处理已经被问过很多次了 但我仍然找不到一个简单的方法来做到这一点 walk

随机推荐