限制类型参数在数据声明中可以采用的类型
Limiting the Types that a Type Paramater Can Take On in Data Declarations
我知道 Haskell 具有参数化数据类型:
data Maybe a = Nothing | Just a
但是有没有办法限制 a
可以表示的类型?特别是,我想创建一个类型
data Tag a = Tag a
这样 a
可以采用 类型 TagPrimitive
或 类型 TagComplex
(但是,我不希望 a
的类型可能是 Integer
或 String
或在我的程序中没有意义的类型)。
这可能吗?
您可以使用通常的单例方法:
{-# language GADTs #-}
data Taggable a where
Primitive : Taggable TagPrimitive
Complex : Taggable TagComplex
然后定义Tag
为
data Tag a where
Tag : Taggable a -> a -> Tag a
然后当你调度给定 Tag
值的 a
时,你可以只匹配单例:
f :: Tag a -> T
f (Tag Primitive x) = ... - here, you know x :: TagPrimitive
f (Tag Complex x) = ... -- here, you know x :: TagComplex
或者,正如@rampion 在评论中提到的那样,您可以将 Taggable
折叠成 Tag
,留下
data Tag a where
Primitive :: TagPrimitive -> Tag TagPrimitive
Complex :: TagComplex -> Tag TagComplex
您提议的 Tag
类型有点奇怪:它是一个参数化类型,可以专门用于 仅 可以包含 TagPrimitive
的类型s 或 可能专门用于 仅 包含 TagComplex
的类型。但这似乎有点毫无意义:我们已经有两个专门的类型 TagPrimitive
和 TagComplex
来服务这两个角色。
相反,我建议您真正想要的是可以包含任一类型值的单一类型。为此,我建议准备一个新的总和类型:
data Tag = Primitive TagPrimitive | Complex TagComplex
deriving (Eq, Ord, Read, Show)
对于早期原型,您可能会使用规范求和类型 Either
,如
type Tag = Either TagPrimitive TagComplex
但我怀疑随着程序的增长,这将变成 increasingly bad choice。
我知道 Haskell 具有参数化数据类型:
data Maybe a = Nothing | Just a
但是有没有办法限制 a
可以表示的类型?特别是,我想创建一个类型
data Tag a = Tag a
这样 a
可以采用 类型 TagPrimitive
或 类型 TagComplex
(但是,我不希望 a
的类型可能是 Integer
或 String
或在我的程序中没有意义的类型)。
这可能吗?
您可以使用通常的单例方法:
{-# language GADTs #-}
data Taggable a where
Primitive : Taggable TagPrimitive
Complex : Taggable TagComplex
然后定义Tag
为
data Tag a where
Tag : Taggable a -> a -> Tag a
然后当你调度给定 Tag
值的 a
时,你可以只匹配单例:
f :: Tag a -> T
f (Tag Primitive x) = ... - here, you know x :: TagPrimitive
f (Tag Complex x) = ... -- here, you know x :: TagComplex
或者,正如@rampion 在评论中提到的那样,您可以将 Taggable
折叠成 Tag
,留下
data Tag a where
Primitive :: TagPrimitive -> Tag TagPrimitive
Complex :: TagComplex -> Tag TagComplex
您提议的 Tag
类型有点奇怪:它是一个参数化类型,可以专门用于 仅 可以包含 TagPrimitive
的类型s 或 可能专门用于 仅 包含 TagComplex
的类型。但这似乎有点毫无意义:我们已经有两个专门的类型 TagPrimitive
和 TagComplex
来服务这两个角色。
相反,我建议您真正想要的是可以包含任一类型值的单一类型。为此,我建议准备一个新的总和类型:
data Tag = Primitive TagPrimitive | Complex TagComplex
deriving (Eq, Ord, Read, Show)
对于早期原型,您可能会使用规范求和类型 Either
,如
type Tag = Either TagPrimitive TagComplex
但我怀疑随着程序的增长,这将变成 increasingly bad choice。