Haskell function for checking permutations

If I declare data constructors such as

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)

How can I make a function

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

to verify that two cities are not given the same team name. For example, the following will return True, but if any "Name" is assigned to more than one city, it will return False.

test1 :: City -> Name
test1 c = case c of
    Baltimore  -> Orioles
    Chicago    -> Cubs
    Seattle    -> Mariners
    Miami      -> Marlins
    Toronto    -> Blue Jays
+4
source share
1 answer

Try the following:

import Data.List (nub)

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

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

This basically checks if the function is f :: City -> Name injective .

In fact, we can create a more general predicate 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

Hope this helps.

+5
source

Source: https://habr.com/ru/post/1608097/


All Articles