Jef*_*eff 3 haskell functional-programming
我想创建一个名为TwoValued的类型,它包含两个值:TwoValued
和a
,我想确保这一点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)
据我所知,你不能在构造函数中定义逻辑.换句话说,构造函数用于区分值和保存参数.
但是,您可以隐藏构造函数,并定义执行构造的函数.例如:
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
以便其他模块可以获取参数.
正如其他人已经提到的那样,聪明的构造函数是惯用的方法。
另外,我们也可以使用“智能模式构造器”,它允许逻辑超出常规逻辑。
{-# 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
仅在模块内可访问哑构造函数。从外面看,我们只能使用聪明的人。
但是,这是一个好主意还是有争议的。我想我们还没有习惯期望构造函数包含一些逻辑。将昂贵的计算隐藏在构造背后可能会使用户感到惊讶。