I'm attempting to implement functor for a record object that has a function attribute, something like this:
data Function a =
Function {
, funcApply :: FData -> [Exp a] -> Either (RawException a) (Exp a)
}
The funcApply attribute therefore needs to fmap to the type FData -> [Exp b] -> Either (RawException b) (Exp b).
Mapping over the return values seems simple enough, and gets me to the type FData -> [Exp a] -> Either (RawException b) (Exp b):
instance Functor Function where
fmap f (Function funcApply) =
let funcApply' = \fData exps ->
case funcApply fData exps of
Left x -> Left $ fmap f x
Right x -> Right $ fmap f x
in Function funcApply'
But I really can't see how to map over the function arguments. Logically, it feels like funcApply shouldn't need to be changed at all, as it's already polymorphic, but it seems that the compiler disagrees.
Any help gratefully received!
The type should be designed with regard to the desired instance. You figure out what mapping is useful for your purpose and structure your type to reflect it. As has been pointed out it is not possible to be Functorial in an argument that appears with mixed polarity.
A common trick is to split the argument by polarity,
Then you also get a valid
Functor (Function іn)Your solution from the comment, to make it polymorphic also works. It means there is no parameter to map over so it can't have higher-kinded instances like Functor or Profunctor.
Being polymorphic is a double-edged sword. You are free to instantiate it however you want
\(Function fn) -> fn @(Int -> Int)but it places severe restrictions on what counts as a function.