# How to represent semigroup homomorphism and similars?

**URL:** <https://discourse.haskell.org/t/how-to-represent-semigroup-homomorphism-and-similars/4321>\
**Category:** Learn\
**Created:** [April 3, 2022, 6:17am UTC](https://discourse.haskell.org/t/how-to-represent-semigroup-homomorphism-and-similars/4321 "2022-04-03T06:17:12Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Abab9579](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/abab9579/32/2163_2.png) [@Abab9579](https://discourse.haskell.org/u/Abab9579)\
**Post date:** [April 3, 2022, 6:17am UTC](https://discourse.haskell.org/t/how-to-represent-semigroup-homomorphism-and-similars/4321/1 "2022-04-03T06:17:12Z")

</div>

What is the idiomatic way to represent a semigroup/monoid homomorphism?

I know that it is impossible to encode the conditions, but I also think simply using normal functions for homomorphism is against the type-driven practice typical in haskell.

In particular, I need a place to put `f (a <> b) = f a <> f b` as a verbal constraint. I thought about using typeclasses, but typeclass quite not fits here.

What I want is linear maps, smooth maps and such, but representing monoid homomorphism could be a great start.  
So what is the idiomatic way to do this?

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [April 3, 2022, 11:42am UTC](https://discourse.haskell.org/t/how-to-represent-semigroup-homomorphism-and-similars/4321/2 "2022-04-03T11:42:25Z")

</div>

How about a type `newtype MonoidHomomorphism a b = MonoidHomomophism (a -> b)`.

EDIT: added `newtype`

---

<div class="post-metadata">

**Author:** ![Abab9579](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/abab9579/32/2163_2.png) [@Abab9579](https://discourse.haskell.org/u/Abab9579)\
**Post date:** [April 3, 2022, 12:27pm UTC](https://discourse.haskell.org/t/how-to-represent-semigroup-homomorphism-and-similars/4321/3 "2022-04-03T12:27:35Z")

</div>

You mean newtype? Is it idiomatic haskell to use newtype and explain in comments that it should satisfy certain constraints? Because I heard somewhere that it isn’t good practice to use newtype to enforce constraint…

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [April 3, 2022, 12:29pm UTC](https://discourse.haskell.org/t/how-to-represent-semigroup-homomorphism-and-similars/4321/4 "2022-04-03T12:29:22Z")

</div>

> [@Abab9579](#):
>
> ? Is it idiomatic haskell to use newtype and explain in comments that it should satisfy certain constraints?

Seems perfectly reasonable to me.

---

<div class="post-metadata">

**Author:** ![Abab9579](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/abab9579/32/2163_2.png) [@Abab9579](https://discourse.haskell.org/u/Abab9579)\
**Post date:** [April 3, 2022, 12:31pm UTC](https://discourse.haskell.org/t/how-to-represent-semigroup-homomorphism-and-similars/4321/5 "2022-04-03T12:31:37Z")

</div>

I see, let me go with it. And I thought verbal constraint only applies to typeclasses!!

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [April 3, 2022, 1:04pm UTC](https://discourse.haskell.org/t/how-to-represent-semigroup-homomorphism-and-similars/4321/6 "2022-04-03T13:04:52Z")

</div>

A common pattern of verbal contracts with newtypes are [smart constructors](https://wiki.haskell.org/Smart_constructors). Usually you define them in an `*.Internal` module and then only expose safe functions in public modules.

Although, in the case of monoid homomorphisms it is not really possible to make a function that decides whether some function is a monoid homomorphism or not, so this approach cannot be made fully watertight. I could imagine that you could use property-based testing to at least reject functions that are clearly not homomorphisms, but even that sounds difficult.

I would say that a newtype with verbal warnings on unsafe functions is the easiest idiomatic way to do this.

Edit: Here’s an example of my property-based testing idea:

```haskell
{-# LANGUAGE FlexibleContexts #-}

import Test.LeanCheck

newtype MonoidHomomorphism a b = MkMonoidHomomorhpism
  {runMonoidHomomorphism :: a -> b}

mkMonoidHomomorphism ::
  (Listable a, Show a, Monoid a, Monoid b, Eq b) =>
  (a -> b) ->
  Maybe (MonoidHomomorphism a b)
mkMonoidHomomorphism f
  | f mempty == mempty
    , holds 100 (\x y -> f x <> f y == f (x <> y)) =
    Just (MkMonoidHomomorhpism f)
  | otherwise = Nothing

```

Obvious downsides are:

- limited to types that implement the required classes, especially [`Listable`](https://hackage.haskell.org/package/leancheck-0.9.10/docs/Test-LeanCheck.html#t:Listable)
- probably poor performance at runtime
- not actually a proof

---

<div class="post-metadata">

**Author:** ![Abab9579](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/abab9579/32/2163_2.png) [@Abab9579](https://discourse.haskell.org/u/Abab9579)\
**Post date:** [April 3, 2022, 1:16pm UTC](https://discourse.haskell.org/t/how-to-represent-semigroup-homomorphism-and-similars/4321/7 "2022-04-03T13:16:17Z")

</div>

Thanks for detailed explanations!  
Btw, is it common practice to use long names like `MonoidHomomorphism`?

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [April 3, 2022, 1:22pm UTC](https://discourse.haskell.org/t/how-to-represent-semigroup-homomorphism-and-similars/4321/8 "2022-04-03T13:22:00Z")

</div>

I think it is a relatively long name, but I can’t think of a better shorter one.
