多态性类型:使用相同类型的同义词表示多种类型
我的目标是给出两种数据类型相同的同义词。 我将我的问题最小化了以下问题:
{-# LANGUAGE KindSignatures, Rank2Types #-}
class Things (h :: * -> *) where
newtype Thing1 a = Thing1 a
newtype Thing2 a = Thing2 a
instance Things Thing1 where
instance Things Thing2 where
type OneOfTwo a = forall h. Things h => h a
foo :: OneOfTwo String -> String
foo (Thing1 name) = name
foo (Thing2 name) = name
我的目标是能够制作类型的同义词OneOftwo
代表Thing> Thing> Thing> Thing> Thing> Thing> thite> thits> thite2 thing2
(如果我愿意的话,甚至更多)。但是,当我这样做时,除了foo
中的第一个模式外,任何匹配的模式都将被视为多余的:
Pattern match is redundant
|
15 | foo (Thing2 name) = name
|
我知道我可以将其重新编写为以下内容:
newtype Thing1 a = Thing1 a
newtype Thing2 a = Thing2 a
data OneOfTwo a = One (Thing1 a)
| Two (Thing2 a)
foo :: OneOfTwo String -> String
foo (One (Thing1 name)) = name
foo (Two (Thing2 name)) = name
但是我想避免创建创建新的数据类型OneOftwo
。
是否有解决方法可以实现这一目标而不创建新的拳击数据类型?
My objective is giving two data types the same synonym.
I've minimized my question to the following question:
{-# LANGUAGE KindSignatures, Rank2Types #-}
class Things (h :: * -> *) where
newtype Thing1 a = Thing1 a
newtype Thing2 a = Thing2 a
instance Things Thing1 where
instance Things Thing2 where
type OneOfTwo a = forall h. Things h => h a
foo :: OneOfTwo String -> String
foo (Thing1 name) = name
foo (Thing2 name) = name
My goal is to be able to make the type synonym oneOfTwo
stand for either Thing1
and Thing2
(or even more if I want to). But when I do so, any pattern matching aside from the first one in foo
will be seen as redundant:
Pattern match is redundant
|
15 | foo (Thing2 name) = name
|
I'm aware that I can re-write it as the following:
newtype Thing1 a = Thing1 a
newtype Thing2 a = Thing2 a
data OneOfTwo a = One (Thing1 a)
| Two (Thing2 a)
foo :: OneOfTwo String -> String
foo (One (Thing1 name)) = name
foo (Two (Thing2 name)) = name
But I want to avoid creating a new data type OneOfTwo
.
Is there a workaround to make this happen without creating a new boxing data type?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您已经尝试构建存在类型
的意思是“使用Value
V
的人Oneoftwo a
可以确保有一些具体类型构造函数h
,它是things
的实例,因此v
具有类型h a
”。但这不是 您写的类型是什么意思;那是通用类型,这意味着对于 act 类型构造函数
h
v
的用户可能会想到,<代码> v 具有类型h a
。即单个值v
一般具有多种不同类型!这意味着,尽管在不同的构造函数上匹配,但您实际上可以编写
案例匹配的两个将成功!之所以起作用,是因为在每个
案例
表达式中,v
专门针对不同的h
实例化,这是可以的,因为类型是通用的。Haskell实际上没有存在类型。正如您所指出的那样,它确实具有歧视总量类型。它还可以模拟具有普遍量化的数据构造函数的存在类型,可优先用GADT语法表达:
这使得在概念上可以将类似于( 此代码不起作用)的东西成为
可能实际上获得该功能,您需要将案例区别放在课堂实例中,就像
You've tried to build an existential type
meaning “whoever uses a value
v
of typeOneOfTwo a
can be sure that there is some concrete type constructorh
, which is an instance ofThings
, such thatv
has typeh a
”. But that's not what the type you wrote means; that is a universal typemeaning that for all type constructors
h
that the user ofv
might think of,v
has typeh a
. I.e. the single valuev
has in general multiple different types!That means you can actually write
and both of the case matches will succeed, despite matching on different constructors! This works because in each of the
case
expressions,v
is specialised to a differenth
instantiation, which is ok because the type is universal.Haskell doesn't really have existential types. It does, as you've noted, have discriminated sum types. It also can simulated existential types with universally quantified data constructors, preferrably expressed with GADT syntax:
which makes it conceptually possible to have something like (this code doesn't work)
To actually get that functionality, you need to put the case distinction into the class instances, like
出于明显指出的风险,类型类的全部目的是允许您定义可以应用于多种类型的多态性功能,因此在这种情况下您假定要做的是写:
也就是说,当您要用单个名称表示多种类型时,要使用的工具是类型类,而不是类型的同义词。
At the risk of pointing out the obvious, the whole purpose of type classes is to allow you to define polymorphic functions that can be applied to multiple types, so what you're supposed to do in this situation is write:
That is, when you want to represent multiple types with a single name, the tool you want to use is a type class, not a type synonym.