3

I'm currently working through the book Thinking with Types. In the third chapter Variance, the author provides an exercise in which the reader should implement the functor instance for T1.

newtype T1 a = T1 (Int -> a)

I found a couple of ways to make this type check, e.g.,

instance Functor T1 where
  fmap f (T1 a) = T1 (f . a)

…and

instance Functor T1 where
  fmap f (T1 a) = T1 (f <$> a)

Of course just making the instance type check doesn't mean that the instance respects the functor laws. To try and test that the instance I write is correct (and thus show that at least one of the instances written above are wrong), I'd like to write some property-based tests.

I would like to use the hedgehog-classes library to write my tests. The library provides the lawsCheck and functorLaws functions that I believe I will need. I imagine I could test my instances with the following line in GHCi

> lawsCheck (functorLaws genT1)

What I'm missing is how to write genT1, which I imagine would generate one (or perhaps several? Should it actually be genT1List?) random T1 value(s). Do I need to use something like hedgehog-fn to generate arbitrary functions so I can make some random (Int -> a) values for T1 to wrap? If so, how?

Jezen Thomas
  • 13,619
  • 6
  • 53
  • 91
  • 3
    (Spoiler: Both instances are correct. Check the definition of Functor for functions: `instance Functor ((->) r) where ...`) – Hjulle May 09 '21 at 12:09
  • You might be able to use something like `functorLaws $ fmap (T1 . apply) <$> fn`, but in order to use `functorLaws` the container `T1` must be an instance of both `Eq` and `Show`, which it isn't. So now you have the new problem of figuring out how to implement lawful instances of those type classes, which isn't obvious. – Mark Seemann May 09 '21 at 13:02
  • Note that, in this specific case, `f <$> a` is defined as `f . a`, so there's no difference between the two instances you mention. – chi May 09 '21 at 17:34
  • I'm glad I either seem to have developed an intuition for how to do the right thing or perhaps I'm lucky and persistent with my guesswork, but I'm still not any closer to understanding how to write the property-based tests for these instances. – Jezen Thomas May 09 '21 at 19:01

0 Answers0