Function types as monoid instances

I have a function that looks like

transition :: State -> ([State], [State])

      

Given the specific domain of my problem, I know how to group two sequential function calls transition

, something like this:

transition `chain` trainsition ... `chain` transition

      

However, I would like to express this as Monoid

and chaining with <>

and mappend

. Unfortunately, I cannot get the following or similar options to work:

instance Monoid (State -> ([State], [State])) where
    mempty  = ...
    mappend = ...

      

The returned error looks like this:

β€’ Illegal instance declaration for
    β€˜Monoid (State -> ([State], [State]))’
    (All instance types must be of the form (T a1 ... an)
     where a1 ... an are *distinct type variables*,
     and each type variable appears at most once in the instance head.
     Use FlexibleInstances if you want to disable this.)
β€’ In the instance declaration for
    β€˜Monoid (State -> ([State], [State]))’

      

In general, how can functions be expressed as instances Monoid

?

+3


source to share


1 answer


Functions are already instances of monoids in a different way . How do you expect Haskell to decide to use this instance or your instance? The usual way to solve your problem is to declare a wrapper newtype

like

newtype Transition a = Transition { runTransition :: a -> ([a], [a]) }

      

Then you can make your monoid instance just fine:

instance Monoid (Transition a) where
  mempty  = ...
  mappend = ...

      



After that, you may even find it foldMap

helpful. Instead of writing something like

runTransition (Transition  transition `chain`
               Transition  transition `chain`
               ...
               Transition  transition)

      

you can use foldMap

runTransition (foldMap Transition [transition, transition, ... transition])

      

+7


source







All Articles