我想创建一个名为TwoValued的类型,它包含两个值:a
和b
,我想确保a <= b
data TwoValued a b | a <= b = ValuePair a b
| otherwise = ValuePair b a
但它不起作用,我认为守卫方程式不允许在这里,所以还有其他方法可以实现我想要的吗?感谢。
答案 0 :(得分:10)
这里需要一个ADT(抽象数据类型),因此,首先,正确创建数据类型:
data TwoValued a = ValuePair a a deriving Show
然后制作构造函数
makePair :: Ord a => a -> a -> TwoValued a a
makePair x y = if x < y then (ValuePair x y) else (ValuePair y x)
最后,只使用用户需要查看的函数(在本例中为makePair)导出模块
答案 1 :(得分:6)
据我所知,您无法在构造函数中定义逻辑。用粗体表示,构造函数用于区分值和保持参数。
然而,你可以隐藏构造函数,并定义函数来执行构造。例如:
module Foo(TwoValued(), twoValued, firstValue, secondValue)
data TwoValued a = ValuePair { firstValue :: a, secondValue :: a}
twoValued :: Ord a => a -> a -> TwoValued a
twoValued a b | a <= b = ValuePair a b
| otherwise = ValuePair b a
因此,我们定义了一个数据结构TwoValued
并将其导出而不是构造函数(我们编写module Foo(TwoValued())
,注意module Foo(TwoValued(..))
)以及函数{{ 1}}就像构造函数一样。
我们还可以导出getters twoValued
和firstValue :: TwoValued a -> a
,以便其他模块可以获取参数。
答案 2 :(得分:4)
智能构造函数是惯用的方法,正如其他人已经评论过的那样。
作为替代方案,我们也可以使用&#34;智能模式构造器&#34;,它允许逻辑超越常规逻辑。
{-# LANGUAGE PatternSynonyms #-}
module SmartCons(OrdPair(OrdPair)) where
data OrdPair = OP Int Int
pattern OrdPair :: Int -> Int -> OrdPair
pattern OrdPair x y <- OP x y where
OrdPair x y = if x <= y then OP x y else OP y x
然后我们可以按预期使用它们:
> import SmartCons
> case OrdPair 3 2 of OrdPair x _ -> x
2
请注意,OP
哑构造函数只能在模块中访问。从外面看,我们只能使用聪明的。