fp-ts icon indicating copy to clipboard operation
fp-ts copied to clipboard

Is it correct to define concatAll for Magma?

Open SHND opened this issue 1 year ago • 3 comments

Looking at the code for concatAll for Magma here, is it correct to define concatAll for Magma? This is how it is implemented right now in fp-ts:

export const concatAll =
  <A>(M: Magma<A>) =>
  (startWith: A) =>
  (as: ReadonlyArray<A>): A =>
    as.reduce((a, acc) => M.concat(a, acc), startWith)

The definition of Magma is only mentioning that concat ing 2 elements of a Set, should result in an element in that Set (Set is closed under the concat operation). But it doesn't necessarily an Associative operation. In that case we can have a scenario for Magma that:

concat(x, concat(y, z)) !== concat(concat(x, y), z)

If that is so, then from the definition of Magma, it seems that we cannot define a concatAll because the order of way we concat elements matter and we cannot abstract over it using a function! because function at the end of the day needs to concat elements in some specific order.

Do we even care for Magma s in TypeScript? I cannot think of any Magma s which are not already a Semigroup in TypeScript!

I really like to see what everyone thinks.

SHND avatar Mar 11 '23 19:03 SHND

because function at the end of the day needs to concat elements in some specific order.

Outside of typeclass methods, the type signature of a function and its documentation is all that (softly) binds it.

What would a semigroup constraint/dependency change? The function could be - uselessly and misleadingly, but validly - defined as follows either way:

const concatAll = <A>(_M: Semigroup<A>):
  (constVal: A) => (ignored: Array<A>) => A => constant

Do we even care for Magma s in TypeScript? I cannot think of any Magma s which are not already a Semigroup in TypeScript!

I'd tend to agree with that. I've found no use for it except tripping up beginners.

samhh avatar Mar 11 '23 21:03 samhh

@samhh Maybe I'm missing your point here. What is the constant in the concatAll generic function? Maybe constVal right? We cannot use anything else because that's the only A we have here for this generic function. But as you said this is not useful, and we are putting it in the library as a general tool (with an incorrect function name saying we are concatenating-all-of-something).

The way I look at it is, Magma has a concept that comes with its name. By having a concrete implementation of concatAll using function, we are implicitly assuming Associativity rule to it's definition, which then it's not a Magma anymore, and makes it a Semigroup.

In another words, to my opinion we cannot implement a good concatAll function for Magma, unless we assume this Magma is a Semigroup, or we assume that this implementation (mapping of input to output) is one of many ways to implement concatAll for a Magma. (compared to Semigroup which concatAll is a unique mapping between its input and output no matter how we implement it)

SHND avatar Mar 11 '23 22:03 SHND

The way I look at it is, Magma has a concept that comes with its name. By having a concrete implementation of concatAll using function, we are implicitly assuming Associativity rule to it's definition, which then it's not a Magma anymore, and makes it a Semigroup.

The only thing that codifies associativity is the typeclass constraint. As per above we can define alternative behaviours for concatAll that aren't associative, though I don't know if that's ever actually helpful.

samhh avatar Mar 22 '23 12:03 samhh