字面数作为Haskell中的数据构造函数

时间:2015-10-20 03:06:50

标签: haskell

我最近在学习Haskell。我一直想知道我是否可以使用文字数作为数据构造函数,如Integer,Int,Word do。 例如,对于以下代码,

data MyBool = Zero | One
         deriving(Bounded, Eq, Show, Enum)
toBool Zero = False
toBool One = True
fromBool False = Zero
fromBool True = One
myAnd = ff (&&) toBool fromBool
myOr = ff (||) toBool fromBool

ff pp fp pf x y= pf $ pp (fp x) (fp y)

我想要做的是将Zero替换为0,将One替换为1,以便我可以使用类似:myAnd (1::MyBool) (0::MyBool)的内容。 我确实查看了ghc的源代码,我找到了类似的东西:

data Int = GHC.Types.I# GHC.Prim.Int#
data Word = GHC.Types.W# GHC.Prim.Word# 

我研究Int#是'unbox type',它必须是使它们能够使用文字数作为数据构造函数的关键。 那么我怎样才能使我的类型使用文字数作为数据构造函数,如Int和Word呢? (不要犹豫,问问题是否含糊不清。)

1 个答案:

答案 0 :(得分:2)

只需为Num类型创建MyBool个实例并定义:

fromInteger 0 = Zero
fromInteger 1 = One

或者也许:

fromInteger n = if even n then Zero else One

所以它不是偏袒的。

在这种情况下,您可以撰写myAnd 0 1 - 您不会需要::MyBool类型注释。

实例定义可以简短为:

instance Num MyBool where
    fromInteger n = if even n then Zero else One

您会收到有关缺少实施的警告,但如果您不对MyBool值使用这些操作,那么您就可以了。如果你想要一个完整的Num实例,我可能会走这条路:

instance Enum MyBool where
  fromEnum Zero = 0
  fromEnum One  = 1
  toEnum n      = if even n then Zero else One

instance Num MyBool where
  fromInteger   = toEnum . fromInteger
  a + b         = toEnum (fromEnum a + fromEnum b)
  a * b         = toEnum (fromEnum a * fromEnum b)
  negate a      = a
  abs a         = a
  signum        = toEnum . signum . fromEnum

<强>更新

我看到你已经派生了EnumEq,但你可能会想要使用我给出的Enum实例,因为它处理范围[0..1]之外的整数值,它在定义Num实例时非常有用。