限制数据类型构造函数参数

时间:2014-12-29 20:16:23

标签: haskell types

我有类型

data Type1 = A1 | B1 Bool | C1 Char | D1 Double

我需要第二种

data Type2 = A2 Type1

其中A2被限制为仅允许A1或B1

我知道我可以使用像

这样的智能构造函数
mkA2 A1 = A2 A1
mkA2 b@(B1 _) = A2 b

但我想知道有没有办法强制限制类型系统级别?

2 个答案:

答案 0 :(得分:4)

不,这在香草Haskell中是不可能的。你最好把它写成

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

答案 1 :(得分:1)

也许你问的是更多的理论问题?通过花哨的扩展,有很多方法可以解决这类问题。例如,可以使用GADT将C1D1的类型限制为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