4

My student assignment I'm doing for Haskell programming includes a task I'm a little bit puzzled to solve. The things are given so: an instance of Functor class to be created just for a set-based new type. There is a declaration of that:

newtype Set x = Set { contains :: (x -> Bool) }

It's a case for me to understand what means if fmap serves to be applied to something like a set of predicates. When doing about previous tasks, I've already defined fmap rather with functions like (+3) (to alter integers), (toUpper) (to strings) etc. It's first time I'm dealing with anything beyond normal types (various numerics, String, Char). There is my humble attempt to start:

instance Functor Set where
    fmap f (Set x) = if (contains x) == True then Set (f x) else Set x

Surely, it's a nonsense code, but I suppose some True/False need to be evaluated before fmap apllication goes well. But, first of all, would you please explain the matter of set of predicates to elaborate more sensible approach?

Haskell bit
  • 151
  • 8
  • You said "set *of predicates*", but then never talked about the "of predicates" part. I have a hunch that this may be important. What is `PSet`? – luqui Jan 03 '20 at 16:14
  • 1
    What is `Pset`? `Set` is a wrapper around a characteristic function, so for example `Set even` represents the set of even numbers: given `e = Set even`, you can determine if a value `x` is in `e` by evaluating `contains e x`: `contains e 2 == True` and `contains e 3 == False`, for example. `PSet` seems like a data constructor for a *power set*, so `contains x` would simply give you the characteristic function for the set `x`, not a boolean value. – chepner Jan 03 '20 at 16:15
  • I'm sorry for an erroneous `PSet` instead of `Set` just as in the new type declaration. This looks correct now unless noticing my humble code, indeed...@chepner, thank you for your suggestion, I would proceed as per your explanation. Now it seems as much more evident to me. – Haskell bit Jan 03 '20 at 16:26

1 Answers1

9

With this definition, it is actually impossible to define a Functor instance for Set. The reason for this is that your Set a type contains a in a negative position... that is, a is an argument to a function, not a value. When that happens, the type constructor can be a contravariant functor (type class Contravariant from the contravariant package), but it cannot be a covariant functor (the Functor type class).

Here's are definitions of those classes:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

class Contravariant f where
    contramap :: (a -> b) -> f b -> f a

See the difference? In a contravariant functor, the direction of the function you pass in is flipped when it's lifted to operate on the functor type.

In the end, this should make sense. Your notion of a "set" is a test that tells you whether something qualifies or not. This is a perfectly good mathematical definition of a set, but it gives you different computational powers than the standard one. For example, you cannot get at the elements of your predicate-based sets; only wait to be given a potential element. If you have a Set Integer, and a function f :: String -> Integer, then you can test Strings by first converting them to Integers and testing those, so you can get from Set Integer to Set String. But having a g :: Integer -> String doesn't let you test Strings!

If this is an assignment, then either you've misunderstood the assignment, you've done some earlier step differently than expected (e.g., if you defined Set yourself in an earlier part, maybe you need to change the definition), or perhaps your instructor is hoping you'll struggle with this and understand why Functor cannot be defined.

Chris Smith
  • 2,615
  • 19
  • 18
  • Thank you a lot for insight you shared, just appreciable as well as anything which enables better understanding...Let's see, surely I didn't ignore any crucial details to provide with the code of Set. May be, it's just a case to test our reason about Functors and so on. Now I'm likely to see that all much better, it's essential I've got asking my question. – Haskell bit Jan 04 '20 at 07:53