모노이드(및 반군)
12914 단어 haskellfunctionaltypescript
Semigroups 및 monoids은 여러 요소를 하나로 축소하는 매우 일반적인 프로그래밍 작업을 캡처하는 수학적 구조입니다. 이와 같은 형식을 통해 우리는 다른 방법으로는 얻을 수 없는 추상화를 만들고 활용할 수 있으며 공통 언어로 다른 개발자에게 우리의 의도를 알릴 수 있습니다.
모노이드를 이해하려면 먼저 반군으로 시작해야 합니다.
연쇄
Semigroup은 동일한 유형의 두 항목을 함께 연결하는 방법을 공식적으로 정의합니다. 예를 들어 배열은 세미그룹입니다.
[1, 2] <> [3, 4] -- [1, 2, 3, 4]
[1, 2].concat([3, 4]) // [1, 2, 3, 4]
더하기 및 곱하기 아래의 숫자 또는 결합 및 분리 아래의 부울에 대해 반그룹 인스턴스를 동등하게 정의할 수 있습니다. 기본 수학에 관심이 있다면 Wikipedia 에서 semigroups에 대해 자세히 읽을 수 있습니다.
더 흥미로운 것은 우리가 정의한 임의의 유형에 대한 세미그룹을 정의하는 기능입니다.
Cocktail
유형이 있고 그 중 두 가지를 함께 결합할 수 있기를 원한다고 가정해 보겠습니다. 다음과 같이 유형에 대한 정의가 제공됩니다.data Cocktail = Cocktail
{ name :: String
, ingredients :: [String]
}
type Cocktail = {
name: string;
ingredients: string[];
};
그런 다음 모든 칵테일 쌍을 함께 결합할 수 있는 형식의 semigroup 인스턴스를 정의할 수 있습니다.
instance Semigroup Cocktail where
a <> b = Cocktail (name a <> " " <> name b) (ingredients a <> ingredients b)
mojito = Cocktail "Mojito" ["rum", "mint"]
robroy = Cocktail "Rob Roy" ["scotch", "bitters"]
combined = mojito <> robroy
-- Cocktail { name = "Mojito Rob Roy", ingredients = ["rum", "mint", "scotch", "bitters"] }
const semigroupCocktail: Semigroup<Cocktail> = {
concat: (a, b) => ({
name: a.name + ' ' + b.name,
ingredients: a.ingredients.concat(b.ingredients),
}),
};
const mojito: Cocktail = { name: 'Mojito', ingredients: ['rum', 'mint'] };
const robroy: Cocktail = { name: 'Rob Roy', ingredients: ['scotch', 'bitters'] };
// { name: 'Mojito Rob Roy', ingredients: ['rum', 'mint', 'scotch', 'bitters'] }
const combined = semigroupCocktail.concat(mojito, robroy);
그리고 우리의 유형을 함께 결합할 수 있습니다! 물론, 우리는 semigroup 형식 없이 이 두 가지 특정 유형을 함께 연결하는 함수를 정의할 수 있지만 이 수학 용어에 익숙한 개발자에게는 한눈에 덜 명확하고 일반적인 추상화에서 재사용할 가능성이 적습니다. 당신은 오리 타이핑에 의존해야 하고 어떤 법률의 준수에 의존할 수 없었습니다. 말하자면, semigroup 유형 클래스를 사용하는 것은 소비자가 유용한 가정을 할 수 있도록 하는 수학적 및 기능적 추상화에서 일반적인 것인 associativity의 법칙을 준수하는 것을 의미합니다.
재미있는 사실: (시도한) semigroup 인스턴스가 연관되지 않은 경우 실제로는 a magma 입니다! 유형 클래스 계층 구조에 존재하지만 연관되지 않고 반그룹도 아닌 마그마를 정의하는 것은 예외적으로 드뭅니다.
신원
우리는 이제 물건을 결합하는 방법을 알고 있지만 아무것도 없을 경우 어떻게 될까요? 이러한 상황에서 우리는 identity element 가 있는 단순히 반군인 모노이드를 정의할 수 있습니다.
ID 요소는 해당 유형의 다른 요소와 결합하여 해당 유형에 대한 변경 사항이 없는 유형의 값입니다. 예를 들어 문자열의 ID는
''
, 덧셈 아래 숫자0
, 곱셈 아래 숫자1
, 합 아래 부울true
등입니다.배열의 식별 요소는 빈 배열입니다. 이 식별 요소를 주어진 배열에 적용할 때 항상 해당 배열을 변경하지 않고 다시 가져오는 방법을 확인하십시오.
[1, 2] <> [] -- [1, 2]
[] <> [1, 2] -- [1, 2]
[1, 2].concat([]) // [1, 2]
[].concat([1, 2]) // [1, 2]
이전의
Cocktail
유형은 어떻습니까? 두 필드가 각각 이미 모노이드임을 감안할 때 이것은 매우 간단합니다.instance Monoid Cocktail where
mempty = Cocktail mempty mempty
const monoidCocktail: Monoid<Cocktail> = getStructMonoid({
name: monoidString,
ingredients: A.getMonoid<string>(),
});
그리고 이와 같이 임의의 수의 칵테일을 결합할 수 있습니다.
mconcat [] -- Cocktail { name = "", ingredients = [] }
mconcat [mojito] -- Cocktail { name = "Mojito", ingredients = ["rum", "mint"] }
mconcat [mojito, robroy] -- Cocktail { name = "Mojito Rob Roy", ingredients = ["rum", "mint", "scotch", "bitters"] }
fold(monoidCocktail)([]) // { name: '', ingredients: [] }
fold(monoidCocktail)([mojito]) // { name: 'Mojito', ingredients: ['rum', 'mint'] }
fold(monoidCocktail)([mojito, robroy]) // { name: 'Mojito Rob Roy', ingredients: ['rum', 'mint', 'scotch', 'bitters'] }
이것은 semigroup 연결 연산을 함수로 사용하고 monoidal identity 요소를 시작 값으로 사용하여 항목 배열을 줄이는 것과 같습니다.
이 게시물은 내 개인 블로그에서도 찾을 수 있습니다.
https://www.samhh.com/blog/monoids-semigroups
Reference
이 문제에 관하여(모노이드(및 반군)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/samhh/monoids-and-semigroups-2b94텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)