用于检查排列的 Haskell 函数

Posted

技术标签:

【中文标题】用于检查排列的 Haskell 函数【英文标题】:Haskell function to check permutation 【发布时间】:2015-12-16 07:04:37 【问题描述】:

如果我声明数据构造函数,例如

data City = Baltimore | Chicago | Seattle | Miami | Toronto
        deriving (Bounded, Enum, Eq, Ord, Show)

data Name = Orioles | Cubs | Mariners | Marlins | BlueJays
        deriving (Bounded, Enum, Eq, Ord, Show)

我怎样才能做一个函数

checkPermutation :: (City -> Name) -> Bool

检查没有两个城市被分配了相同的团队名称。例如,以下将返回 True,但如果将任何“名称”分配给多个城市,则会返回 False。

test1 :: City -> Name
test1 c = case c of
    Baltimore  -> Orioles
    Chicago    -> Cubs
    Seattle    -> Mariners
    Miami      -> Marlins
    Toronto    -> Blue Jays

【问题讨论】:

【参考方案1】:

试试这个:

import Data.List (nub)

cities :: [City]
cities = [Baltimore..Toronto]

checkPermutation :: (City -> Name) -> Bool
checkPermutation f = (== length cities) . length . nub . map f $ cities

这基本上是检查函数f :: City -> Name是否为injective。

其实我们可以创建一个更通用的injective谓词:

import Data.Set as Set

typeSet :: (Bounded a, Enum a, Ord a) => Set a
typeSet = fromList $ enumFrom minBound

injective :: (Enum a, Bounded a, Ord a, Ord b) => (a -> b) -> Bool
injective f = let xs = typeSet in (== size xs) . size . Set.map f $ xs

希望对您有所帮助。

【讨论】:

您可以通过添加Ord 约束并使用集合而不是nub 来提高效率(如果这是一个问题)。 我是否需要在 if 语句中以某种方式将“checkPermutation f = (== length urban).length .nub .map f $citys”放在一个 if 语句中,以便我可以返回 true 或 false?此外,ghci 不喜欢“cities = [Baltimore..Toronto]”,说部分必须用括号括起来,而不是在范围内 @user2988976 不,(== length cities) 函数本身返回一个布尔值。此外,如果您使用 GHCi,则需要输入 let cities = [Baltimore..Toronto]

以上是关于用于检查排列的 Haskell 函数的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 null 函数而不是 == [] 来检查 Haskell 中的空列表?

在 Haskell 中创建一个检查字谜的函数

Haskell检查函数是不是两次返回相同的值

为啥我的 Haskell 函数参数必须是 Bool 类型?

Haskell - 简单的构造函数比较(?)函数

Haskell中是否有“继续”?