Monoid Instance

Hi all!

I need some guidance with Monoids. Help will be highly appreciated!
I had some code that I decided to refactor in Haskell fashion. I have a data structure:

data TwoFungiblesAndWitness = TwoFungiblesAndWitness with
    f1     : FungibleImplementation.Fungible
    f2     : FungibleImplementation.Fungible
    witness: Party

And I have a list of functions that return Bool for this type:

isWitnessOwner: TwoFungiblesAndWitness -> Bool
isWitnessOwner TwoFungiblesAndWitness{ f1, f2, witness } = f1.account.owner == witness  && f2.account.owner == witness

isSameAccount: TwoFungiblesAndWitness -> Bool
isSameAccount TwoFungiblesAndWitness{ f1, f2 } = f1.account == f2.account

isSameInstrument: TwoFungiblesAndWitness -> Bool
isSameInstrument TwoFungiblesAndWitness{ f1, f2 } = f1.instrument == f2.instrument

Now I want to pass my data through this list and return True only if all functions return True.
At the current moment, I do it like this:

isMergeable twoFungiblesAndWitness = all ((==True) . ($ twoFungiblesAndWitness)) [isWitnessOwner, isSameAccount, isSameInstrument]

And this is fine. But I want to add foldMap to my arsenal. So after learning I came up with this:

isMergeable = getAll . foldMap (All .) predicates
    where predicates = [isWitnessOwner, isSameAccount, isSameInstrument]

I get an error here:

No instance for (Monoid (TwoFungiblesAndWitness -> All))
        arising from a use of ‘foldMap’

How can I implement such an instance? As I understand I need to tell the compiler how to act with a list of functions, how concat results, etc…
I tried

instance Monoid (TwoFungiblesAndWitness -> All) where
  mempty _ = All True 

But I do not feel confident about what I should do here.


I think this is a case where making it more generic actually makes things a bit easier to understand: The Monoid instance we’re looking for here is Monoid b => Monoid (a -> b) so if the result type is a Monoid, the function is also a monoid. Looking at this we can also see that we need to combine the results. We can do that by just applying both functions to the same argument and then combining the results:

instance Semigroup b => Semigroup (a -> b) where
  f <> g = \x -> f x <> g x

instance Monoid b => Monoid (a -> b) where
  mempty = const mempty

Cool! Thanks!
This is the default Monoid implementation for any type, right? Can I think about it this way?
Since I didn’t specify any specific type, just added this code to the file and that’s it

I’d call it a “generic implementation”. default usually implies that you might overwrite it for some times. You wouldn’t really do that here usually.