softshipper
softshipper

Reputation: 34071

Semigroup with data type that contains function

I have following data type and Semigroup instance of it:

newtype Combine a b = 
  Combine { unCombine :: a -> b }

instance (Semigroup b) 
  => Semigroup (Combine a b) where 
  Combine {unCombine=f} <> Combine {unCombine=g} = Combine (f <> g)

What does Combine (f <> g) mean? I pass the function f and g to the binary operator <> what is the output of it?

To figure out how it works, I try to play a bit in prelude:

Prelude> let f = Combine $ \n -> Sum (n + 1)
Prelude> let g = Combine $ \n -> Sum (n - 1)
Prelude> unCombine (f <> g) $ 0
Sum {getSum = 0}

For me it looks like a function composition f after g, but am I not sure, how does exactly work. Could someone tell me, how does it work?

Another example(maybe it does not make sense):

*Exercises Data.Semigroup> data Zoo a b = Zoo (a -> b)
*Exercises Data.Semigroup> x = Zoo (+23)
*Exercises Data.Semigroup> :t x
x :: Num b => Zoo b b

How to use x?

Upvotes: 2

Views: 114

Answers (1)

chi
chi

Reputation: 116139

f <> g is calling the library instance for functions:

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

So, it is defined pointwise.

Perhaps using generalized newtype deriving would have been better here, since Combine has exactly the same instance. One might even wonder if Combine is needed at all.

Upvotes: 4

Related Questions