gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 10:26:38 25 4
gpt4 key购买 nike

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

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

我想创建两种类型 XY,这样 X 类型的值可以是 ABC,如下所示:

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

并且 Y 类型的值只能是 AB,如下所示:

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

我知道我可以将构造函数包装在 XY 的定义中,如下所示:

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

但这看起来很不整洁(必须一直输入XA A等)。我可以将 ABC 的内容扩展为 XY 的定义,但是A等非常复杂,我不想重复定义。

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

编辑

似乎 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 中(着眼于更“实用”而不是“学术”语言)。

编辑2

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

最佳答案

类型类,如 jetxee所描述的,可能是合适的方法。

如果您还希望能够进行模式匹配和使用构造函数,那么您可以使用 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

现在,仅使用 AB 的函数适用于 XY 类型。使用 C 的函数仅适用于 X 类型。

关于haskell - 属于两种不同类型的一个值构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4256502/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com