1

I'm studying Haskell and I was asked to solve this exercise:

Implement a new data type named NovoPred that should have a value constructor with the same name. Also it should have a field named runNovoPred with type Maybe a -> Bool Then, create an Functor Contravariant instance for type NovoPred

In order to solve this exercise, I've made this solution:

module Oitavo where

import           Data.Functor.Contravariant

newtype NovoPred a =
  NovoPred
    { runNovoPred :: Maybe a -> Bool
    }

instance Contravariant NovoPred where
    contramap y (NovoPred x) = NovoPred (x . y)

As you may notice, this solution doesn't work at all. Contramap needs to have this structure: (a -> b) -> f b -> f a, the problem is that x function expects to receive a value that looks like Maybe b and it is actually receiving a value b because that is what y function returns. Therefore, it is impossible to do x . y, because x expects to receive a value that doesn't match with what y is actually returning.

So, I think I need a way to make y function return a value of type Maybe b. Unfortunately, I don't have a clue on how to do it since contramap expects to receive something like a -> b as first parameter instead of something like a -> Maybe b (that's what I need). Could you give me a hand with that?

chrometic
  • 81
  • 5
  • 3
    In `NovoPred (x . something)`, the `something` not only should return a `Maybe a` but also it receives a `Maybe b`. Now how can you construct such a function from `y :: b -> a`? – Bergi Oct 12 '19 at 22:41

1 Answers1

5

If you have a function y :: a -> b and you need to convert a Maybe a to a Maybe b, you can just fmap over Maybe:

contramap y (NovoPred x) = NovoPred (x . fmap y)
Fyodor Soikin
  • 78,590
  • 9
  • 125
  • 172