모나드는 endofunctors 범주의 단일체입니다. 문제는 무엇입니까?


722

누가 먼저 다음을 말했습니까?

모나드는 endofunctors 범주의 단일체입니다. 문제는 무엇입니까?

그리고 덜 중요한 점에서 이것은 사실입니까? 그렇다면 설명을 제시 할 수 있습니까?


14
"작업 수학자 카테고리"
돈 스튜어트

19
Haskell에서 모나드를 사용하기 위해 이것을 이해할 필요는 없습니다. 실제적인 관점에서 그들은 지하 배관을 통해 "상태"를 통과하는 영리한 방법 일뿐입니다.
starblue

1
이 훌륭한 블로그 게시물을 여기에 추가하고 싶습니다 : stephendiehl.com/posts/monads.html 질문에 직접 대답하지는 않지만 Stephen은 Haskell에서 카테고리와 모나드를 함께 묶는 훌륭한 일을합니다. 위의 답변을 읽은 경우이를 보는 두 가지 방법을 통합하는 데 도움이됩니다.
벤 포드

3
보다 정확하게는 "C 카테고리의 경우, endofunctors의 카테고리 [C, C]는 컴포지션에 의해 유발 된 단일체 구조를 갖습니다. [C, C]의 단일체는 C의 모나드입니다." -en.wikipedia.org/wiki/Monoid_%28category_theory%29에서 카테고리 이론에서 모나드의 정의는 en.wikipedia.org/wiki/Monad_%28category_theory%29를 참조하십시오.

1
@Dmitry functor 는 범주 간 함수이며 일부 제약 조건이 있습니다. 카테고리 C의 endofunctor는 C에서 그 자체로 functor 일뿐입니다. Data.FunctorHask 범주의 endofunctor에 대한 형식 클래스 입니다. 범주는 객체와 형태로 구성되므로 functor는 두 가지 모두를 매핑해야합니다. Data.Functor의 인스턴스 f의 경우, 오브젝트의 맵 (haskell 유형)은 f 자체이고 모프 식 (haskell 함수)의 맵은 fmap입니다.
Matthijs

답변:


795

제임스 아이리 (James Iry) 는 프로그래밍 언어의 매우 간단하고 불완전하며 대부분 잘못된 프로그래밍 언어의 역사 에서 필립와 들러 (Fhilip Wadler)의 허구에 속한다고 주장했다.

원래 인용문은 카테고리 이론의 기본 텍스트 중 하나 인 작업 수학자를위한 카테고리의 Saunders Mac Lane에서 인용 한 것입니다. 여기에 문맥이 있으며 , 이것이 의미하는 바를 정확히 배우는 가장 좋은 장소 일 것입니다.

그러나 나는 찌를 것이다. 원래 문장은 다음과 같습니다.

모두 말했듯이, X의 모나드는 X의 endofunctor 카테고리에서 단일체이며, 곱 ×는 endofunctor의 구성으로 대체되고 단위 endofunctor로 설정된 단위로 대체됩니다.

X 는 카테고리입니다. Endofunctors은 (일반적으로 자체 범주에서 펑있는 모든 Functor -하지만 난의 탈선 유형의 범주가 대부분 하나의 카테고리로 다루고 있기 때문에, 지금까지의 기능 프로그래머에 관한 한 S). 그러나 " X의 endfunctors"범주 인 다른 범주를 상상할 수 있습니다. 이것은 객체가 endofunctors이고 형태가 자연스러운 변형 인 범주입니다.

그리고 그 endofunctors 중 일부는 모나드 일 수 있습니다. 모나드는 어느 것입니까? 정확히 어떤 의미에서 단일체 인 것입니다 . 모나드에서 모노 이드로의 정확한 매핑을 철자하는 대신 (맥 레인이 기대했던 것보다 훨씬 우수하기 때문에) 각각의 정의를 나란히 놓고 비교해 보도록하겠습니다.

단일체는 ...

  • 세트, S
  • 작업, • : S × S → S
  • S 의 요소 , e : 1 → S

...이 법규를 충족시키는 것 :

  • S의 모든 a , bc 에 대해 (a • b) • c = a • (b • c)
  • S 에서 모든 a 에 대해 e • a = a • e = a

모나드는 ...

  • endofunctor, T : X → X (하스켈에서 인스턴스 * -> *와 같은 유형 생성자 Functor)
  • 천연 변형, T × T → T : μ , × 수단 펑 조성물 ( μ가 라고도 join하스켈)
  • 자연 변환, I → T : η , 에 대한 신원 endofunctor입니다 X ( η가 로 알려져있다 return하스켈이)

...이 법규를 충족시키는 것 :

  • μ ∘ Tμ = μ ∘ μT
  • μ ∘ Tη = μ ∘ ηT = 1 (정체 자연 변환)

약간의 흠집이 생기면이 두 정의가 동일한 추상 개념의 인스턴스라는 것을 알 수있을 것 입니다 .


21
설명, 불완전하고 대부분 잘못된 프로그래밍 언어 이력 기사에 대한 설명과 감사에 감사드립니다. 나는 그것이 거기에서있을 것이라고 생각했다. 진정한 프로그래밍 유머 중 하나입니다.
Roman A. Taycher

6
@Jonathan : monoid의 고전적인 공식에서 × 는 세트의 데카르트 곱을 의미합니다. en.wikipedia.org/wiki/Cartesian_product 에서 자세한 내용을 읽을 수 있지만 기본 아이디어는 S × T 의 요소 가 쌍 (s, t) 이며 여기서 s ∈ St ∈ T 입니다. 따라서이 맥락에서 monoidal product의 시그니처 • : S × S-> S 는 단순히 S의 두 요소 를 입력으로 사용하고 S의 다른 요소를 출력으로 생성 하는 기능을 의미합니다 .
Tom Crockett

12
@TahirHassan-카테고리 이론의 일반성에서 우리는 세트 대신 불투명 한 "객체"를 다루므로 "요소"에 대한 선입관이 없습니다. 그러나 객체가 세트이고 화살표가 함수 인 카테고리 세트 에 대해 생각 하면 세트 S의 요소는 하나의 요소 세트에서 S 로의 기능과 일대일로 대응됩니다. 원소 ES는 , 정확히 하나 개의 함수가 -> S 1 : F , 1은 어느 하나의 요소 세트이다 (계속)
톰 크로켓

12
@TahirHassan 1- 요소 세트는 그 자체가 "터미널 객체"의보다 일반적인 카테고리 이론적 개념을 전문화 한 것입니다. 터미널 객체는 다른 객체에서 정확히 하나의 화살표가있는 카테고리의 모든 객체입니다. 이것은 Set 의 1 요소 세트에 해당 합니다. 범주 이론에서 터미널 객체는 간단히 1 이라고합니다 . 그것들은 동형에 특유하므로 그것들을 구별 할 요점이 없다. 이제 우리는 모든 S에 대한 " S의 요소"에 대한 순전히 범주 이론적 설명을 갖습니다 . 그것들은 1 에서 S 까지의 화살표 일뿐입니다 !
톰 크로켓

7
@TahirHassan-이것을 Haskell 용어로 표현하려면 S, 함수 f :: () -> S가 타입 이라면 함수를 작성할 때 할 수있는 모든 것이 타입의 특정 용어 S(필요하다면 "요소")를 골라 리턴 한다는 사실을 생각하십시오 그것은 ... 당신은 인수에 대한 실제 정보를 얻지 못 했으므로 함수의 동작을 바꿀 수있는 방법이 없습니다. 따라서 f매번 같은 것을 반환하는 상수 함수 여야합니다. ()( "Unit")은 Hask 범주의 터미널 객체이며, 정확히 1 (비 발산) 값이 존재한다는 것은 우연이 아닙니다.
톰 크로켓

532

직관적으로, 나는 멋진 수학 어휘가 말하는 것은 다음과 같습니다.

모노 이드

모노 이드는 객체의 세트, 및 이들을 조합 한 방법이다. 잘 알려진 monoid는 다음과 같습니다.

  • 추가 할 수있는 숫자
  • 연결할 수있는 목록
  • 당신이 노조 수 설정

더 복잡한 예도 있습니다.

또한 모든 monoid에는 identity 가 있습니다. 즉, "no-op"요소는 다른 것과 결합 할 때 효과가 없습니다.

  • 0 + 7 == 7 + 0 == 7
  • [] ++ [1,2,3] == [1,2,3] ++ [] == [1,2,3]
  • {} 유니언 {apple} == {apple} 유니언 {} == {apple}

마지막으로, monoid는 연관 이어야합니다 . (왼쪽에서 오른쪽으로 개체의 순서를 변경하지 않는 한 원하는대로 긴 조합의 문자열을 줄일 수 있습니다) 추가는 괜찮습니다 ((5 + 3) +1 == 5+ (3+ 1)), 뺄셈은 ((5-3) -1! = 5- (3-1))이 아닙니다.

모나드

이제 특별한 종류의 세트와 객체를 결합하는 특별한 방법을 생각해 봅시다.

사물

집합에 특별한 종류의 함수 가 포함되어 있다고 가정합니다 . 이 함수에는 흥미로운 서명이 있습니다. 숫자를 숫자로, 문자열을 문자열로 전달하지 않습니다. 대신, 각 함수는 2 단계 프로세스에서 숫자를 숫자 목록으로 전달합니다.

  1. 0 개 이상의 결과 계산
  2. 그 결과를 어떻게 든 단일 답변으로 결합하십시오.

예 :

  • 1-> [1] (입력을 랩핑)
  • 1-> [] (입력을 버리고 목록에 아무것도 포함하지 않음)
  • 1-> [2] (입력에 1을 더하고 결과를 줄 바꿈)
  • 3-> [4, 6] (입력에 1을 더하고 입력에 2를 곱하고 여러 결과를 줄 바꿈 )

객체 결합

또한 함수를 결합하는 방법은 특별합니다. 함수를 결합하는 간단한 방법은 구성입니다 . 위의 예를 들어 각 함수를 자체적으로 구성 해 보겠습니다.

  • 1-> [1]-> [[1]] (입력을 두 번 줄 바꿈)
  • 1-> []-> [] (입력을 버리고, 목록에서 아무것도 감싸지 않음, 두 번)
  • 1-> [2]-> [UH-OH! ] (목록에 "1을 추가 할 수 없습니다!")
  • 3-> [4, 6]-> [UH-OH! ] (1 개의 목록을 추가 할 수 없습니다!)

유형 이론에 너무 많이 들어 가지 않으면 요점은 두 정수를 결합하여 정수를 얻을 수 있지만 항상 두 함수를 구성하고 동일한 유형의 함수를 얻을 수는 없다는 것입니다. ( a-> a 유형 기능 은 작성되지만 a-> [a] 는 작성되지 않습니다.)

함수를 결합하는 다른 방법을 정의 해 봅시다. 이 두 가지 기능을 결합하면 결과를 "이중 랩핑"하고 싶지 않습니다.

여기 우리가하는 일이 있습니다. 두 함수 F와 G를 결합하려면 다음과 같은 프로세스를 따릅니다 ( 바인딩 ).

  1. F에서 "결과"를 계산하되 결합하지 마십시오.
  2. G를 각 F의 결과에 개별적으로 적용하여 결과를 계산하여 결과 모음을 생성합니다.
  3. 2 단계 모음을 병합하고 모든 결과를 결합합니다.

예제로 돌아가서,이 새로운 "바인딩"함수 방식을 사용하여 함수를 결합 (바인딩) 해 봅시다.

  • 1-> [1]-> [1] (입력 랩핑, 두 번)
  • 1-> []-> [] (입력을 버리고, 목록에서 아무것도 감싸지 않음, 두 번)
  • 1-> [2]-> [3] (1을 추가 한 다음 1을 다시 추가하고 결과를 랩핑하십시오.)
  • 3-> [4,6]-> [5,8,7,12] (1을 입력에 추가하고 입력에 2를 곱하여 두 결과를 모두 유지 한 다음 두 결과에 모두 다시 수행 한 후 최종 마무리 목록에 표시됩니다.)

이보다 복잡한 함수 결합 방법 연관성 있습니다 (멋진 랩핑 작업을 수행하지 않을 때 함수 구성이 연관되는 방식에 따라).

모두 함께 묶어

  • 모나드는 함수의 결과를 결합하는 방법을 정의하는 구조입니다.
  • monoid가 객체를 결합하는 방법을 정의하는 구조와 비슷한 방식으로,
  • 조합 방법이 연관성이있는 경우
  • 어떤과 결합 될 수있는 특별한 '아니오 조합'이있는 곳 무언가 에 결과에 뭔가 변화가.

노트

결과를 "포장"하는 방법에는 여러 가지가 있습니다. 결과가 없는지 확인하고 상태의 사이드카를 첨부하거나 로그 메시지를 인쇄하는 등의 작업을 수행하면서 목록 또는 집합을 만들거나 첫 번째 결과를 제외한 모든 것을 버릴 수 있습니다.

나는 본질적으로 기본적인 아이디어를 직관적으로 얻기 위해 정의와 약간 느슨하게 연주했습니다.

모나드가 a- > [a] 유형 함수에서 작동한다고 주장함으로써 상황을 약간 단순화했습니다 . 실제로 모나드는 a- > mb 유형 함수에서 작동 하지만 일반화는 주요 통찰력이 아닌 기술적 세부 사항입니다.


22
이것은 모든 모나드는 구성 방법에 대한 좋은 설명입니다 범주를 합니다 ( Kleisli 범주 -이 또한있는 Eilenberg - 무어의 카테고리에있는 거 시연은 무엇인가). 그러나 사실로 인해 사용자가 구성 할 수없는 어떤 두 Kleisli 화살표를 a -> [b]하고 c -> [d](있는 경우에만이 작업을 수행 할 수 있습니다 b= c)이 꽤 모노 이드를 설명하지 않습니다. 실제로는 "모노 이드 연산자"인 함수 구성이 아니라 설명한 병합 작업입니다.
Tom Crockett

6
모나드를 하나의 유형으로 만 제한 한 경우, 즉 양식의 Kleisli 화살표 만 허용하면 a -> [a]이것이 단일체가됩니다 (Kleisli 범주를 단일 객체로, 하나의 객체로만 분류하기 때문에) 정의에 따르면 monoid입니다!) 그러나 모나드의 전체 일반성을 포착하지는 못합니다.
Tom Crockett

5
마지막으로, a-> [a]는-> [] a라는 것을 기억하는 것이 좋습니다. ([]는 형식 생성자이기도합니다.) 따라서-> mb로 표시 될뿐만 아니라 []는 실제로 Monad 클래스의 인스턴스입니다.
Evi1M4chine

8
이것은 모나드와 문자 그대로 몇 주 동안 만난 모노 이드에 대한 수학적 배경에 대한 가장 훌륭하고 설명 가능한 설명입니다. 모나드에 관해서는 모든 Haskell 책에 인쇄해야합니다. 찬양하라! 모나드는 하스켈에 넣은 것을 포스트에 넣는 매개 변수화 된 유형 클래스 인스턴스로 실현된다는 정보를 얻을 수 있습니다. (적어도 지금은 내가 지금까지 그것을 이해 한 방법입니다. 내가 틀렸다면 정정하십시오. haskell.org/haskellwiki/What_a_Monad_is_not 참조 )
sjas

1
이것은 환상적입니다-다른 사람에게 설명 할 수있을만큼 충분히 잘 이해 한 유일한 설명입니다 ... 그러나 이것이 왜 이것이 무엇인가를 생각할 수있는 귀중한 방법인지 이해하지 못합니다. :(
Adam Barnes

84

먼저 우리가 사용할 확장과 라이브러리 :

{-# LANGUAGE RankNTypes, TypeOperators #-}

import Control.Monad (join)

이 중 RankNTypes아래에 반드시 필요한 유일한 것입니다. 한 번은 RankNTypes일부 사람들이 유용하다고 생각되는 것에 대한 설명을 썼습니다 .

Tom Crockett의 훌륭한 답변을 인용 하면 다음과 같습니다.

모나드는 ...

  • endofunctor, T : X-> X
  • 천연 변형, μ : T × T -> T 여기서 × 수단 펑 조성물
  • 자연 변환, η : I-> T , 여기서 나는 X 의 정체성 endofunctor입니다

...이 법규를 충족시키는 것 :

  • μ (μ (T × T) × T)) = μ (T × μ (T × T))
  • μ (η (T)) = T = μ (T (η))

이것을 하스켈 코드로 어떻게 번역합니까? 자연 변환 의 개념부터 시작해 봅시다 .

-- | A natural transformations between two 'Functor' instances.  Law:
--
-- > fmap f . eta g == eta g . fmap f
--
-- Neat fact: the type system actually guarantees this law.
--
newtype f :-> g =
    Natural { eta :: forall x. f x -> g x }

형태의 유형은 f :-> g함수 유형과 유사하지만, 대신으로 생각의 기능 둘 사이의 유형 (종류 *)하는으로 생각 morphism에 둘 사이에 (가지 각 * -> *). 예 :

listToMaybe :: [] :-> Maybe
listToMaybe = Natural go
    where go [] = Nothing
          go (x:_) = Just x

maybeToList :: Maybe :-> []
maybeToList = Natural go
    where go Nothing = []
          go (Just x) = [x]

reverse' :: [] :-> []
reverse' = Natural reverse

기본적 하스켈, 자연 변환 일부 유형의 함수이다 f x다른 유형 g x되도록 x입력 변수가 호출자에게 "액세스"된다. 예를 들어, sort :: Ord a => [a] -> [a]어떤 유형으로 인스턴스화 할 수 있는지에 대한 까다롭기 때문에 자연 변환으로 만들 수 없습니다 a. 이것을 생각하기 위해 자주 사용하는 한 가지 직관적 인 방법은 다음과 같습니다.

  • 펑 터는 구조 를 건드리지 않고 무언가 의 내용 을 조작하는 방법입니다 .
  • 자연스러운 변형은 내용을 보거나 보지 않고 무언가 의 구조 를 조작하는 방법입니다 .

이제 그 방법으로 정의의 절을 다루겠습니다.

첫 번째 절은 "endofunctor, T : X-> X "입니다. Functor하스켈의 모든 사람들은 사람들이 "하 스크 범주"라고 부르는 엔도 펀터이며, 그 개체는 하스켈 유형 (종류 *)이고 그 형태는 하스켈 함수입니다. 이것은 복잡한 진술처럼 들리지만 실제로는 매우 사소한 진술입니다. 그 의미 모든 것을이가 있다는 것이다 Functor f :: * -> *당신에게 유형 구성의 수단 제공 f a :: *어떤을위한 a :: *및 기능 fmap f :: f a -> f b어떤 아웃을 f :: a -> b하고, 이러한 순종 그 펑터 법.

두 번째 절 : IdentityHaskell 의 functor (플랫폼과 함께 제공되므로 가져올 수 있음)는 다음과 같이 정의됩니다.

newtype Identity a = Identity { runIdentity :: a }

instance Functor Identity where
    fmap f (Identity a) = Identity (f a)

따라서 Tom Crockett의 정의에서 자연 변환 η : I-> T 는 모든 Monad경우에 t다음과 같이 쓸 수 있습니다 .

return' :: Monad t => Identity :-> t
return' = Natural (return . runIdentity)

세 번째 조항 : Haskell에서 두 개의 functor의 구성은 다음과 같이 정의 할 수 있습니다 (플랫폼과 함께 제공됨).

newtype Compose f g a = Compose { getCompose :: f (g a) }

-- | The composition of two 'Functor's is also a 'Functor'.
instance (Functor f, Functor g) => Functor (Compose f g) where
    fmap f (Compose fga) = Compose (fmap (fmap f) fga)

따라서 Tom Crockett의 정의에서 자연 변환 μ : T × T-> T 는 다음과 같이 쓸 수 있습니다.

join' :: Monad t => Compose t t :-> t
join' = Natural (join . getCompose)

이것이 endofunctors 범주에서 monoid라는 진술은 Compose(부분적으로 첫 두 매개 변수에만 부분적으로 적용됨) 연관성 Identity이 있고 그것이 식별 요소라는 것을 의미합니다. 즉, 다음과 같은 동형이 있습니다.

  • Compose f (Compose g h) ~= Compose (Compose f g) h
  • Compose f Identity ~= f
  • Compose Identity g ~= g

이 매우 간단하기 때문에 입증하기입니다 ComposeIdentity모두로 정의 newtype하고, 하스켈 보고서의 의미 정의 newtype유형 사이의 동형 정의 된대로와의 인수의 유형 newtype의 데이터 생성자를. 예를 들어 다음과 같이 증명해 봅시다 Compose f Identity ~= f.

Compose f Identity a
    ~= f (Identity a)                 -- newtype Compose f g a = Compose (f (g a))
    ~= f a                            -- newtype Identity a = Identity a
Q.E.D.

새로운 유형에서는 제약 조건이 Natural무엇인지 파악할 수 없습니다 (Functor f, Functor g). 설명해 주시겠습니까?
dfeuer

@dfeuer 실제로 필수적인 것은 아닙니다.
Luis Casillas

1
@LuisCasillas Functor필요하지 않은 것 때문에 이러한 제약 조건을 제거했습니다 . 동의하지 않으면 자유롭게 다시 추가하십시오.
Lambda Fairy

functors의 제품이 구성으로 간주되는 것이 공식적으로 의미하는 바를 자세히 설명 할 수 있습니까? 특히, functor 구성에 대한 투영 형태는 무엇입니까? 내 생각에 제품은 functor F에 대해서만 정의되며 F x F 및 join정의 된 경우에만 정의됩니다. 그리고 그것이 join투영의 형태입니다. 그러나 나는 확실하지 않다.
tksfz

6

참고 : 아니요, 사실이 아닙니다. 어느 시점에서 Dan Piponi 자신의 대답은 여기에 원인과 결과가 정확히 반대라고 말했으며 James Iry의 quip에 대한 기사를 썼습니다. 그러나 그것은 아마도 일부 강박적인 정리에 의해 제거 된 것 같습니다.

아래는 내 원래 답변입니다.


Iry가 Dan Piponi (sigfpe)가 Haskell의 monoids에서 모나드를 유도하는 게시물 인 Monoids에서 Monads로 읽었을 가능성이 매우 높으며 , 범주 이론에 대한 설명과 " Hask 의 endofunctors 범주"에 대한 언급이 많았습니다 . 어쨌든 모나드가 endofunctors 범주에서 단일체가되는 것이 무엇을 의미하는지 궁금해하는 사람은이 파생물을 읽는 것이 도움이 될 수 있습니다.


1
"아마도 강박적인 사람에 의해"-또는 우리가이 사이트에서 그들을 참조하기 위해 중재자 :-)입니다.
halfer

6

나는 Mac Lane의 작업 이론가에 대한 카테고리 이론 에서 악명 높은 인용을 추론하는 것을 더 잘 이해하기 위해이 게시물에 왔습니다 .

무엇인가를 기술 할 때, 그것이 아닌 것을 묘사하는 것이 종종 똑같이 유용합니다.

Mac Lane이 설명을 사용하여 Monad를 설명한다는 사실은 모나드 고유의 것을 설명하고 있음을 의미 할 수 있습니다. 나와 함께 참아 이 진술에 대한 이해 를 넓히기 위해서는 모나드 고유의 것을 묘사하고 있지 않다는 것을 분명히해야한다고 생각합니다 . 그 진술은 다른 것들 중에서도 적용과 화살을 동일하게 묘사합니다. 같은 이유로 우리는 Int (Sum and Product)에 두 개의 monoid를 가질 수 있으며 endofunctors 범주에서 X에 여러 개의 monoid를 가질 수 있습니다. 그러나 더 많은 유사점이 있습니다.

Monad와 Applicative는 모두 다음 기준을 충족합니다.

  • 엔도 => 화살표 또는 같은 장소에서 시작하고 끝나는 형태
  • functor => 화살표 또는 두 범주 사이의 형태

    (예 : 매일 Tree a -> List b이지만 카테고리 Tree -> List)

  • monoid => 단일 객체; 즉, 단일 유형이지만, 이러한 맥락에서, 외부 층에 대해서만; 그래서, 우리는 할 수 없습니다 Tree -> ListList -> List.

명령문은 "...의 범주 ..."를 사용합니다. 이는 명령문의 범위를 정의합니다. 예를 들어, Functor Category는 f * -> g *, 즉 Any functor -> Any functor, Tree * -> List *또는 의 범위를 나타 Tree * -> Tree *냅니다.

범주 형 진술에서 명시하지 않은 것은 무엇이든 무엇이 허용 되는지를 기술한다 .

이 경우 펑터 내부에서 * -> *일명 a -> b지정되지 않습니다 Anything -> Anything including Anything else. 내 상상력이 Int-> String으로 이동하면 Integer -> Maybe Int, 또는 Maybe Double -> Either String Intwhere 도 포함됩니다 a :: Maybe Double; b :: Either String Int.

따라서 진술은 다음과 같이 구성됩니다.

  • functor 범위 :: f a -> g b(즉, 모든 매개 변수화 된 유형에서 모든 매개 변수화 된 유형)
  • 엔도 + 펑터 :: f a -> f b(즉, 동일한 매개 변수화 된 유형에 대한 임의의 매개 변수화 된 유형) ...
  • endofunctor 범주의 단일체

이 구조물의 힘은 어디에 있습니까? 전체 역학을 이해하기 위해, 나는 monoid (Identity arrow처럼 보이는 단일 객체)의 전형적인 그림이, :: single object -> single object내가 원하는 수 의 monoid 값으로 매개 변수화 된 화살표를 사용할 수 없다는 것을 설명하지 못하고 , Monoid에서 허용 되는 하나의 유형 객체에서. 동등성의 엔도, 아이덴티티 화살표 정의 는 functor의 타입 값 과 가장 안쪽의 "페이로드"레이어의 타입과 값을 모두 무시 합니다 . 따라서 등변 유형이 일치하는 모든 상황에서 동등성이 리턴 됩니다 (예 : 둘 다이므로 동등 합니다 ).trueNothing -> Just * -> NothingJust * -> Just * -> Just *Maybe -> Maybe -> Maybe

사이드 바 : ~ outside는 개념이지만에서 가장 왼쪽에있는 기호입니다 f a. 또한 "Haskell"이 무엇을 먼저 읽었는지 설명합니다 (큰 그림). 따라서 유형은 유형 값과 관련하여 "외부"입니다. 프로그래밍에서 계층 (참조 체인) 간의 관계는 범주와 관련이 없습니다. 집합 범주는 Functor 범주 (매개 변수 유형)를 포함하는 유형 (Int, Strings, Maybe Int 등)을 설명하는 데 사용됩니다. 참조 체인 : Functor 유형, Functor 값 (Functor 세트의 요소 (예 : Nothing, Just)) 및 각 Functor 값이 가리키는 모든 항목. 범주에서 관계는 다르게 설명됩니다. 예를 들어, return :: a -> m a지금까지 언급 된 것과는 다른 하나의 Functor에서 다른 Functor 로의 자연 변환으로 간주됩니다.

정의 된 텐서 제품과 중립적 인 가치에 대한 주 스레드로 돌아가서, 그 진술은 역설적 구조에서 태어난 놀랍도록 강력한 계산 구조를 설명합니다.

  • 외부에서는 단일 객체 (예 :)로 나타납니다 :: List. 공전
  • 내부는 많은 역학을 허용합니다
    • 임의의 arity의 기능에 대한 사료와 동일한 유형 (예 : Empty | ~ NonEmpty)의 모든 값. 텐서 제품은 외부 레이어 ( fold페이로드에 대해 아무 말도하지 않음)에 대해 여러 입력을 단일 값으로 줄입니다.
    • 무한 범위 모두 내주 가장 층의 형태 및 값

하스켈에서는 진술의 적용 가능성을 명확히하는 것이 중요합니다. 이 구성의 힘과 다양성은 모나드 그 자체 와 전혀 관련이 없습니다 . 다시 말해, 구성은 모나드를 고유하게 만드는 것에 의존하지 않습니다.

서로에 의존하는 계산과 병렬로 실행될 수있는 계산을 지원하기 위해 공유 컨텍스트를 사용하여 코드를 작성할지 여부를 알아낼 때,이 악명 높은 설명은 설명하는 것과는 대조적이지 않습니다. Applicative, Arrows 및 Monads가 아니라 그것들이 얼마나 같은지에 대한 설명입니다. 당면한 결정에 대해서는 성명서가 허술하다.

이것은 종종 오해됩니다. 이 진술은 join :: m (m a) -> m amonoidal endofunctor에 대한 텐서 제품 으로 설명하기 위해 계속됩니다 . 그러나,이 진술의 맥락에서 어떻게 (<*>)또한 선택 될 수 있었 는지를 분명히 밝히지는 않았다 . 그것은 실제로 여섯 / 반 다스의 예입니다. 값을 결합하는 논리는 정확히 같습니다. Int를 결합 할 때 서로 다른 결과를 생성하기 때문에 Int에 대한 Sum 및 Product monoid와 달리 동일한 입력은 각각에서 동일한 출력을 생성합니다.

요약하자면, endofunctors 범주의 monoid는 다음을 설명합니다.

   ~t :: m * -> m * -> m *
   and a neutral value for m *

(<*>)(>>=)모두는 2 개 개의 동시 액세스를 제공 m하여 하나의 리턴 값을 계산하기 위해 값. 반환 값을 계산하는 데 사용되는 논리는 정확히 같습니다. 매개 변수화하는 기능의 다른 모양 ( f :: a -> bvs k :: a -> m b)과 계산의 동일한 반환 유형으로 매개 변수의 위치 가 아닌 경우 (예 : 각각 a -> b -> b대 비교 b -> a -> b), 단일 논리를 매개 변수화 할 수 있다고 생각합니다. 텐서 제품, 두 가지 정의 모두에서 재사용. 지점을 만드는 연습으로 시도하고 구현 ~t, 당신은으로 끝낼 (<*>)하고 (>>=)당신이 그것을 정의하기로 결정 방법에 따라 forall a b.

마지막 포인트가 개념적으로 사실이라면, Applicative와 Monad 사이의 정확하고 계산상의 차이점, 즉 매개 변수화 기능을 설명합니다. 즉, 차이점은 외부 이러한 유형 클래스의 구현.

결론적으로 맥 레인의 악명 높은 인용문은 Haskell에서 사용되는 관용구를 더 잘 이해하기 위해 Category를 통해 내비게이션을 탐색하는 동안 참조 할 수있는 훌륭한 "goto"meme을 제공했습니다. Haskell에서 강력하게 액세스 할 수있는 강력한 컴퓨팅 용량의 범위를 캡처하는 데 성공했습니다.

그러나 모나드 외부에서 성명서의 적용 가능성을 처음으로 잘못 이해 한 방법과 여기에 전달하고자하는 바에 대한 아이러니가 있습니다. 그것이 설명하는 모든 것은 Applicative와 Monads (그리고 Arrows 사이)와 비슷한 것으로 판명되었습니다. 그것이 말하지 않은 것은 정확하게 작지만 유용한 차이점입니다.

-전자


5

여기의 답변은 모노 이드와 모나드를 모두 정의하는 데 탁월하지만 여전히 질문에 대답하지 않는 것 같습니다.

그리고 덜 중요한 점에서 이것은 사실입니까? 그렇다면 설명을 제시 할 수 있습니까?

여기서 누락 된 문제의 핵심은 소위 범주화 ( monoid) 범주의 단일체 (monoid) 인 "모노 이드 (monoid)"의 다른 개념입니다 . 슬프게도 맥 레인의 책 자체 는 그것을 매우 혼란스럽게 만듭니다 .

모나드 X는 inofofunctors 카테고리에서 monoid이며 X, endofunctor의 ×구성으로 대체되고 단위는 endofunctor로 설정됩니다.

주요 혼란

이것이 왜 혼란 스러운가? 의 endofunctors 범주에서 "모노 이드"를 정의하지 않기 때문입니다 X. 대신,이 문장은 모든 endofunctor 세트에서 monoid를 functor 구성과 함께 바이너리 연산으로, identity functor를 monoidal 단위로 사용하는 것을 제안 합니다. 이것은 완벽하게 잘 작동하며 식별 functor를 포함하고 functor 구성으로 닫힌 endofunctor의 모든 하위 집합을 monoid로 만듭니다.

그러나 이것은 정확한 해석이 아니며, 그 단계에서 그 책이 명확하지 않습니다. Monad f고정 endofunctor이며 컴포지션하에 닫힌 endofunctor의 하위 집합이 아닙니다. 일반적인 구조는 사용하는 f발생 하는 모든 세트 취함으로써 모노 이드를 k-fold 조성물 f^k = f(f(...))f포함 자체, k=0신원에 해당 대응한다 f^0 = id. 그리고 이제 S모든 이들을위한이 모든 힘 의 집합 k>=0은 실제로 "일곱 개는 endofunctor의 구성으로 대체되고 단위는 endofunctor에 의해 설정된 단위"로 단일체가됩니다.

그리고 아직 :

  • 이 monoid S는 모든 functor f또는 문자 그대로의에 대한 자체 맵에 대해 정의 할 수 있습니다 X. 에 의해 생성 된 monoid f입니다.
  • S펑터 조성물 및 아이덴티티 펑터에 의해 주어진 단일체 구조 f는 모나드이거나 존재 하지 않는 것과 관련이 없다 .

더 혼란스럽게하기 위해, "일몰 범주의 모노 노이드"의 정의 는 목차 에서 볼 수 있듯이이 책의 뒷부분에 나옵니다 . 그러나이 개념을 이해하는 것은 모나드와의 관계를 이해하는 데 절대적으로 중요합니다.

(엄격한) 단일체 범주

(모나드 장 VI보다 나중에 오는) Monoids 장 VII에가, 우리는 소위 정의 찾을 엄격한 monoidal 카테고리 트리플로서 (B, *, e), B카테고리이다 bifunctor 고정 된 다른 성분과의 각 구성 요소에 대하여 (펑을 )이며 의 연관성과 단위 법칙을 만족시키는 단위 객체입니다 .*: B x B-> BeB

(a * b) * c = a * (b * c)
a * e = e * a = a

어떤 객체 a,b,cB, 어떤 morphisms에 대해 동일한 정체성 a,b,c으로 e대체 id_e의 신원 morphism에, e. 이제 우리의 관심사 인 경우, B형태론 , 펑터 구성 및 아이덴티티 펑터 X로서 자연 변형 을 가진 endofunctors의 범주가 어디에 있는지 직접 관찰 할 수 있듯이 이러한 모든 법칙이 충족 된다는 것을 관찰하는 것이 유익합니다 .*e

이 책에서 뒤 따르는 것은 "이완 된 (relaxed)" monoidal 카테고리 의 정의인데 , 여기서 법칙은 소위 일관성 관계를 만족하는 일부 고정 된 자연 변형만을 모듈로만 보유 하지만 endofunctor 카테고리의 경우에는 중요하지 않습니다.

단일 범주의 단일체

마지막으로, VII 장 3 절 "모노 이드"에서 실제 정의는 다음과 같습니다.

모노 이드 cmonoidal이 범주 (B, *, e)의 목적은 B두 개의 화살표 (morphisms)

mu: c * c -> c
nu: e -> c

3 개의 다이어그램을 정식으로 만듭니다. 우리의 경우, 이들은 endofunctors 범주의 형태이며, 정확하게 join그리고 return모나드에 해당하는 자연적 변형 입니다. 우리는 조성 할 때 연결도 명확하게 *교체, 더 명시 적 c * c으로 c^2, 여기서 c우리의 모나드이다.

마지막으로, 3 개의 계산 다이어그램 (단일 범주의 모노 이드 정의에서)은 일반 (엄격하지 않은) 단일 범주에 대해 작성된 반면, 우리의 경우, 단일 범주의 일부로 발생하는 모든 자연 변환은 실제로 동일합니다. 이렇게하면 다이어그램이 모나드 정의의 다이어그램과 정확히 동일하게되어 대응이 완료됩니다.

결론

요약하면, 모나드는 정의에 따라 endofunctor이므로 endofunctors 범주의 객체입니다. 여기서 monadic joinreturnoperator 는 특정 (엄격한) monoidal category에서 모노 이드 의 정의를 만족시킵니다 . 반대로, endofunctors의 monoidal 범주의 모든 monoid는 정의에 따라 (c, mu, nu)하나의 객체와 두 개의 화살표로 구성되어 있습니다. 예를 들어 모나드와 동일한 법칙을 만족시키는 두 가지 화살표가 있습니다.

마지막으로, (클래식) 모노 이드와 일류 범주에서 더 일반적인 모노 이드의 주요 차이점에 주목하십시오. 두 개의 화살표 munu상기 더이상 세트의 이진 동작 및 단위 아니다. 대신, 하나의 고정 endofunctor가 c있습니다. Functor 구성 *과 Identity Functor만으로는 모나드에 필요한 완전한 구조를 제공하지는 않습니다.

다른 접근법은 C세트의 모든 셀프 맵의 표준 모노 아이드와 비교하는 것입니다 A. 이진 연산이 컴포지션이며 표준 데카르트 곱을 C x C에 매핑하는 것으로 볼 수 있습니다 C. categorified 모노 이드 지나가는 우리는 데카르트 제품 교체 x펑 조성물 *, 이진 동작 천연 변형으로 교체 얻는다 mu에서 c * cc의 집합이고, join연산자

join: c(c(T))->c(T)

모든 객체에 대해 T(프로그래밍 유형). 고정 된 1 점 세트의 맵 이미지로 식별 할 수있는 클래식 모노 아이드의 항등 요소는 return연산자 모음으로 대체됩니다.

return: T->c(T) 

그러나 이제 더 이상 직교 곱이 없으므로 요소 쌍이 없으므로 이진 연산이 없습니다.


그렇다면 질문의 "이것이 사실입니까?"에 대한 당신의 대답은 무엇입니까? 모나드는 endofunctors 범주에서 단일체라는 것이 사실입니까? 그렇다면, 단일체의 범주 이론 개념과 대수적 단일체 (연관 곱셈과 단위가있는 집합)의 관계는 무엇입니까?
Alexander Belopolsky
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.