我最近在学习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呢?
(不要犹豫,问问题是否含糊不清。)
答案 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
<强>更新强>
我看到你已经派生了Enum
和Eq
,但你可能会想要使用我给出的Enum实例,因为它处理范围[0..1]之外的整数值,它在定义Num实例时非常有用。