DAY 12
0
Software Development

## Definition of a Semigroup

• 一個集合(Set)或稱型別(Type)
• 有 concat method
• 必須符合 associative

Type Signature

``````concat:: Semigroup a => a ~> a -> a
``````

`a` 是 Semigroup 且有 `concat` 這個 method 在內， 則 `a -> a` 成立

Law

associative:

``````concat(concat(a, b), c) = concat(a, concat(b, c))
``````

concat 輸出出來的結果也必須是同一型別!!! 其可以確保其輸出值可以再次進行 concat ，直到我們想要結束為止。

## 從簡單的範例開始

String

``````'Functional'.concat(' ').concat('Programming') // "Functional Programming"
// same as
('Functional'.concat(' ')).concat('Programming')
// same as
'Functional'.concat(' '.concat('Programming'))
``````

Array

Array 也是一個合法的 Semigroup，並且裡面 item 的資料型別可以不同。

``````[1, 2].concat([3, 4]) // [1, 2, 3, 4]
// same as
[1].concat([2, 3]).concat([4])
// same as
[1].concat([2, 3].concat([4]))
``````

Sum & Product

``````const Sum = val => ({
val,
concat: (o) => Sum(val + o.val),
inspect: () => `Sum(\${val})`
})

Sum(1).concat(Sum(1)).val // 2

const Product = val => ({
val,
concat: (o) => Product(val * o.val),
inspect: () => `Product(\${val})`
})

Product(10).concat(Product(10)).val // 100
``````

Any & All

``````const Any = val => ({
val,
concat: (o) => Any(val || o.val),
inspect: () => `Any(\${val})`
})

Any(true).concat(Any(false)).val // true

const All = val => ({
val,
concat: (o) => All(val && o.val),
inspect: () => `All(\${val})`
})

All(true).concat(All(false)).val // false
``````

Intersection

``````const Intersection = (val) => ({
val,
concat: ({ val: oVal }) =>
Intersection(val.filter((x) => oVal.some((y) => x === y))),
inspect: () => `Intersection(\${JSON.stringify(val)})`,
});

Intersection([1, 2, 3]).concat(Intersection([3, 4, 5])).val // [3]
``````

## concatAll

• 一個 Semigroup
• 有初始值
• 是一組陣列
``````const concatAll = R.curry((semi, initValue, arr) =>
arr.map(semi).reduce((acc, val) => acc.concat(val), semi(initValue)))
``````

max

``````const max = concatAll(Max, Number.NEGATIVE_INFINITY);

max([1, 2, 3, 4, 5]).val // 100
``````

some

``````const some = R.curry((predicate, xs) => concatAll(Any, false, xs.map(predicate)))

some(isEven)([2, 4, 6])
``````

every

``````const every = concatAll(All, true)

every(isEven)([2, 4, 6])
``````

## 小結

NEXT: Semigroup II & Monoid