Haskell使用保护等式创建类型

时间:2017-11-13 18:29:33

标签: haskell

我想创建一个名为TwoValued的类型,它包含两个值:ab,我想确保a <= b

data TwoValued a b | a <= b = ValuePair a b
                   | otherwise = ValuePair b a

但它不起作用,我认为守卫方程式不允许在这里,所以还有其他方法可以实现我想要的吗?感谢。

3 个答案:

答案 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 twoValuedfirstValue :: 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哑构造函数只能在模块中访问。从外面看,我们只能使用聪明的。

但是,这是一个好主意还是坏主意是有争议的。我想我们还没有习惯期望构造函数涉及一些逻辑。隐藏在建筑背后的昂贵计算可能会让用户感到惊讶。