[Haskell-beginners] Representing a Set using a boolean function

Robert Weisser Robert.Weisser at gmx.com
Fri Dec 30 23:53:26 CET 2011


 I am working through Thompson's "Haskell The Craft of Functional
 programming", 2nd edition. I am not doing this as part of a class.
 It is just for my own enjoyment.
 I am having a problem with Exercise 16.38. Here is the exercise:
 The abstract data type Set a can be represented in a number of
 different ways. Alternatives include arbitrary lists (rather
 than ordered lists without repetitions) and Boolean valued functions,
 that is elements of the type a -> Bool. Give implementations of
 the type using these two representations.
  
 Note: the book previously showed a representation of Set a using ordered
 lists without repetitions.
 I had no problem representing Set a with arbitrary lists. My problem came
 when I tried to represent Set a with boolean functions. My first question
 was this: which of the following was Thompson asking for?
 newtype Set a = Set (a -> Bool) (version 1)
  
 newtype Set a = Set [a -> Bool] (version 2)
 I decided on version 1. Version 2 did not seem to have any advantage over
 version 1. Also, version 1 resembled something earlier in the book (an
 associative list implemented as a boolean function). I had no trouble with
 functions in the Module export list (see code below) which did not need
 to know the contents of the set. However, when I got to eqSet, I was
 stumped. I don't see how any function can see inside the set. I don't know
 enough Haskell to be certain, but it looks impossible to me. Is there
 something I am missing?
  
 > module Set (
 > Set,
 > empty, -- Set a
 > sing, -- a -> Set a
 > memSet, -- Ord a => Set a -> a -> Bool
 > union, -- Ord a => Set a -> Set a -> Set a
 > inter, -- Ord a => Set a -> Set a -> Set a
 > diff, -- Ord a => Set a -> Set a -> Set a
 > symmDiff, -- Ord a => Set a -> Set a -> Set a 
 > eqSet, -- Eq a => Set a -> Set a -> Bool
 > subSet, -- Ord a => Set a -> Set a -> Bool
 > makeSet, -- Ord a => [a] -> Set a
 > mapSet, -- Ord b => (a -> b) -> Set a -> Set b
 > filterSet, -- (a -> Bool) -> Set a -> Set a
 > foldSet, -- (a -> a -> a) -> a -> Set a -> a
 > showSet, -- (a -> String) -> Set a -> String
 > card) -- Set a -> Int
 > where
 > 
 > import Data.List hiding (union)
 > 
 > instance Eq a => Eq (Set a) where
 > (==) = eqSet
 > 
 > instance Ord a => Ord (Set a) where
 > (<=) = leqSet
 > 
 > newtype Set a = Set (a -> Bool)
 > 
 > empty :: Set a
 > empty = Set $ \_ -> False
 > 
 > sing :: Ord a => a -> Set a
 > sing y = Set $ \x -> x == y
 > 
 > memSet :: Ord a => Set a -> a -> Bool
 > memSet (Set f) x = f x
 > 
 > union :: Ord a => Set a -> Set a -> Set a
 > union s1 s2 = Set $ \x -> memSet s1 x || memSet s2 x
 > 
 > inter :: Ord a => Set a -> Set a -> Set a
 > inter s1 s2 = Set $ \x -> memSet s1 x && memSet s2 x
 > 
 > diff :: Ord a => Set a -> Set a -> Set a
 > diff s1 s2 = Set $ \x -> memSet s1 x && not (memSet s2 x)
 > 
 > symmDiff :: Ord a => Set a -> Set a -> Set a 
 > symmDiff s1 s2 = union (diff s1 s2) (diff s2 s1)
 > 
 > -- Not exported:
 > contents :: Ord a => Set a -> [a]
 > contents (Set f) = undefined
 > 
 > eqSet :: Eq a => Set a -> Set a -> Bool
 > eqSet (Set xs) (Set ys) = undefined
 > 
 > -- Not exported:
 > leqSet :: Ord a => Set a -> Set a -> Bool
 > leqSet (Set xs) (Set ys) = undefined
 > 
 > subSet :: Ord a => Set a -> Set a -> Bool
 > subSet (Set xs) (Set ys) = undefined
 > 
 > makeSet :: Ord a => [a] -> Set a
 > makeSet xs = foldl addElem empty xs 
 > 
 > -- Not exported:
 > addElem :: Ord a => Set a -> a -> Set a
 > addElem (Set f) y = Set g
 > where
 > g x = if x == y then True
 > else f x
 > 
 > mapSet :: Ord b => (a -> b) -> Set a -> Set b
 > mapSet f (Set xs) = undefined
 > 
 > filterSet :: (a -> Bool) -> Set a -> Set a
 > filterSet p (Set xs) = undefined 
 > 
 > foldSet :: (a -> a -> a) -> a -> Set a -> a
 > foldSet f x (Set xs) = undefined
 > 
 > showSet :: (a -> String) -> Set a -> String
 > showSet f (Set xs) = undefined
 > 
 > card :: Set a -> Int
 > card (Set xs) = undefined
 For testing, I used the following. I checked individual
 values for membership in the union, intersection, etc. 
 > list1 = [1..4] :: [Int]
 > list2 = [3..6] :: [Int]
 >
 > set1 = makeSet list1
 > set2 = makeSet list2
 >
 > setUnion = union set1 set2
 > setInter = inter set1 set2
 > setDiff = diff set1 set2
 > setSymmDiff = symmDiff set1 set2
  
  
 Robert Weisser
  



More information about the Beginners mailing list