Haskell使用保护方程来创建类型

Jef*_*eff 3 haskell functional-programming

我想创建一个名为TwoValued的类型,它包含两个值:TwoValueda,我想确保这一点b

data TwoValued a b | a <= b = ValuePair a b
                   | otherwise = ValuePair b a
Run Code Online (Sandbox Code Playgroud)

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

Dam*_*ero 10

您需要这里的ADT(抽象数据类型),因此,首先,正确创建您的数据类型:

data TwoValued a = ValuePair a a deriving Show
Run Code Online (Sandbox Code Playgroud)

然后创建构造函数

makePair :: Ord a => a -> a -> TwoValued a a
makePair x y = if x < y then (ValuePair x y) else (ValuePair y x)
Run Code Online (Sandbox Code Playgroud)

最后,只使用用户需要查看的函数导出模块(在本例中为makePair)

  • 小尼特:如果使用了智能构造函数,我会在`data`声明中省略`ord a =>`部分.AFAIRC,该语法除了限制"TwoValued"事物的构造之外别无其他.这在各地都有先例,例如[`Data.Map`](https://hackage.haskell.org/package/containers-0.5.10.2/docs/src/Data.Map.Internal.html#Map).甚至还有`empty :: Map(Int - > Int)`尽管`Int - > Int`没有`Ord`实例. (4认同)

Wil*_*sem 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
Run Code Online (Sandbox Code Playgroud)

所以我们定义一个数据结构TwoValued并在没有构造函数(我们编写module Foo(TwoValued()),注释module Foo(TwoValued(..)))的情况下导出它,以及一个twoValued像构造函数一样的函数.

我们还可以导出getter firstValue :: TwoValued a -> a,secondValue :: TwoValued a -> a以便其他模块可以获取参数.


chi*_*chi 5

正如其他人已经提到的那样,聪明的构造函数是惯用的方法。

另外,我们也可以使用“智能模式构造器”,它允许逻辑超出常规逻辑。

{-# 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
Run Code Online (Sandbox Code Playgroud)

然后,我们可以按预期使用它们:

> import SmartCons
> case OrdPair 3 2 of OrdPair x _ -> x
2
Run Code Online (Sandbox Code Playgroud)

请注意,OP仅在模块内可访问哑构造函数。从外面看,我们只能使用聪明的人。

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