fp-ts
fp-ts copied to clipboard
Is it correct to define concatAll for Magma?
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.
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 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)
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.