Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 限制类型参数在数据声明中可以采用的类型_Haskell_Types_Singleton Type - Fatal编程技术网

Haskell 限制类型参数在数据声明中可以采用的类型

Haskell 限制类型参数在数据声明中可以采用的类型,haskell,types,singleton-type,Haskell,Types,Singleton Type,我知道Haskell有参数化的数据类型: data Maybe a = Nothing | Just a 但是有没有办法限制a可以表示的类型?特别是,我想创建一个类型 data Tag a = Tag a 这样a可以采用类型TagPrimitive或类型TagComplex(但是,我不希望a可能是类型,例如,Integer或String或在我的程序中没有意义的东西) 这可能吗?您可以使用通常的单例y方法: {-# language GADTs #-} data Taggable a whe

我知道Haskell有参数化的数据类型:

data Maybe a = Nothing | Just a
但是有没有办法限制
a
可以表示的类型?特别是,我想创建一个类型

data Tag a = Tag a
这样
a
可以采用类型
TagPrimitive
或类型
TagComplex
(但是,我不希望
a
可能是类型,例如,
Integer
String
或在我的程序中没有意义的东西)


这可能吗?

您可以使用通常的单例y方法:

{-# language GADTs #-}

data Taggable a where
  Primitive : Taggable TagPrimitive
  Complex : Taggable TagComplex
然后将
标记定义为

data Tag a where
  Tag : Taggable a -> a -> Tag a
然后,当您在给定的
标记的
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

您建议的
标记
类型有点奇怪:它是一种参数化类型,可以专用于只能包含
TagPrimitive
s的类型,也可以专用于只能包含
TagComplex
s的类型。但这似乎有点毫无意义:我们已经有了两种专门的类型
TagPrimitive
TagComplex
,来服务于这两个角色

相反,我建议您实际需要的是一个可以包含任何一种类型的值的单一类型。为此,我建议制作一个新的总和类型:

data Tag = Primitive TagPrimitive | Complex TagComplex
    deriving (Eq, Ord, Read, Show)
对于早期原型,您可以使用规范的和类型,
,如中所示

type Tag = Either TagPrimitive TagComplex

但我怀疑,随着程序的增长,这将成为一个问题。

我想我有点困惑:为什么要使用
标记
类型?你是在寻找
type Tag=TagPrimitive TagComplex
(或者可能是
data Tag=Primitive TagPrimitive | Complex TagComplex
)——也就是说,一个可以包含
TagPrimitive
TagComplex
类型值的单一类型——相反?是的,我很困惑,你是对的。你提到的这两个备选方案中有哪一个更地道吗?这取决于用法。另请参阅,了解您为什么喜欢自定义
数据
声明的一些讨论。但是这种类型不会静态地告诉您它包装了
TagPrimitive
TagComplex
中的哪一个,这可能是OP所需要的。@Cactus Correct。这就是为什么我在写下这个答案之前对这个问题发表了评论。但正如我在第一段中所指出的:
TagPrimitive
TagComplex
类型本身确实静态地保证了它们是哪一种类型!