2016-05-12 73 views
0

我知道,Haskell有paramaterized數據類型類型:限制一個類型Paramater可以採取在數據聲明

data Maybe a = Nothing | Just a 

但是,有沒有辦法來限制排序是a可以表示類型?特別是,我想創建一個類型

data Tag a = Tag a 

這樣a可以採取要麼TagPrimitive類型TagComplex(但是,我不希望它是可能的,a是類型類型,例如,IntegerString或在我的程序中沒有意義的東西)。

這可能嗎?

+0

我想我有點困惑:爲什麼要有'Tag'類型呢?你是在尋找'type Tag = TagPrimitive TagComplex'(或者可能是'Tag Tag = Primitive TagPrimitive | Complex TagComplex') - 也就是一個* single *類型,它可以包含TagPrimitive或TagComplex的值類型 - 而不是? –

+0

是的,我很困惑,你說得對。你提到的這兩種選擇中哪一種更具慣用性? – George

+0

這取決於使用了一下。另請參閱[此問題](http://stackoverflow.com/q/19072930/791604),瞭解您爲什麼更喜歡自定義數據聲明的一些討論。 –

回答

4

你提出Tag類型是有點奇怪:它是一個參數化類型,其可以是專用的類型可以只有包含TagPrimitive s 可能是專門的類型,可以只有包含TagComplex s。但是這似乎有點無意義:我們已經有兩種專門類型TagPrimitiveTagComplex來擔任這兩個角色。

相反,我建議您實際上想要的是一種可以包含任一類型值的單一類型。爲此,我建議炮製新鮮的總和類型:

data Tag = Primitive TagPrimitive | Complex TagComplex 
    deriving (Eq, Ord, Read, Show) 

對於早期的原型,你可以使用規範的總和型,Either脫身,在

type Tag = Either TagPrimitive TagComplex 

,但我懷疑,作爲您程序增長,這將成爲increasingly bad choice

+0

但這種類型不告訴你,靜態,這'TagPrimitive'或'的一個TagComplex'它包裝,這可能是由OP是必需的。 – Cactus

+1

@Cactus正確。這就是爲什麼我在寫這個答案之前就這個問題寫了一個評論。但正如我在第一段中指出:在'TagPrimitive'和'TagComplex'類型本身確實是會保證做到這一點,靜態,關於哪一個他們! –

7

你可以使用通常,單-Y方式:

{-# 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在評論中提到,你可以摺疊成TaggableTag,留給你

data Tag a where 
    Primitive :: TagPrimitive -> Tag TagPrimitive 
    Complex :: TagComplex -> Tag TagComplex 
相關問題