data Type1 = A1 | B1 Bool | C1 Char | D1 Double
,我需要第二类
data Type2 = A2 Type1
其中A2限制,允许A1或B1仅
我知道我可以使用智能构造像
mkA2 A1 = A2 A1
mkA2 [email protected](B1 _) = A2 b
但我不知道有没有办法强制限制类型系统级别?
data Type1 = A1 | B1 Bool | C1 Char | D1 Double
,我需要第二类
data Type2 = A2 Type1
其中A2限制,允许A1或B1仅
我知道我可以使用智能构造像
mkA2 A1 = A2 A1
mkA2 [email protected](B1 _) = A2 b
但我不知道有没有办法强制限制类型系统级别?
不,这是不可能在香草哈斯克尔。你会过得更好写它作为
data Type1 = A1 | B1 Bool
data Type2 = A2 Type1 | C2 Char | D2 Double
这不需要任何语言扩展或类型系统的技巧,它更清楚地看到你的类型的依赖与延伸,而不是限制。如果你想能够在它们之间进行转换,那么你可以做
type2ToType1 :: Type2 -> Maybe Type1
type2ToType1 (A2 x) = Just x
type2ToType1 _ = Nothing
type1ToType2 :: Type1 -> Type2
type1ToType2 = A2
也许你在问更多的理论问题?有很多方法可以通过奇特的扩展来处理这类事情。例如,可以使用GADT将C1
和D1
的类型限制为Char -> Type1()
和Double -> Type1()
,但保留其他构造函数处于打开状态。因此,一切都将是Type1()
类型,但只有前两种可以是例如类型的。 Type1 Bool
。下面是一个变种,也使用-XDataKinds
,只是为了您的娱乐:
{-# LANGUAGE GADTs, DataKinds, KindSignatures #-}
{-# OPTIONS_GHC -Wall #-}
data Status = Special | Common -- This type we will 'promote' to a kind.
-- Its constructors will be used as
-- names of (memberless) types.
data Type (s :: Status) where
A :: Type s
B :: Bool -> Type s
C :: Char -> Type Common
D :: Double -> Type Common
type Type1 = Type Common -- This has the same constructors as your Type1
-- i.e. A, B, C and D
type Type2 = Type Special -- This has as many constructors as your Type2
-- but doesn't need a new declaration and wrapper
-- They are just A and B
mkGeneral :: Type2 -> Type s
mkGeneral A = A
mkGeneral (B b) = B b -- ghc -Wall sees no patterns are missing
mkCommon :: Type2 -> Type1
mkCommon = mkGeneral
mkSpecial :: Type s -> Maybe Type2
mkSpecial A = Just A
mkSpecial (B b) = Just (B b) -- ghc -Wall sees the need for the next line
mkSpecial _ = Nothing