사용자:BaalDL/작업장/모나드

위키백과, 우리 모두의 백과사전.

모나드 (함수형 프로그래밍) 문서를 만들기 위한 페이지입니다.

영어 위키백과일본어 위키백과를 참고로 작성합니다.



모나드(Monad)는 함수형 프로그래밍의 개념으로, 자료형과 결속 연산, 단위 함수로 구성된다. [1] 연산이라는 개념을 서술한다고 할 수 있으며,[2] 함수형 프로그래밍에서 제네릭 프로그래밍을 구현하기 위한 디자인 패턴으로도 여겨진다.[3] 연산을 연결하면서 그 사이에 추가적인 처리를 실행할 수 있다는 점에서 프로그래밍 가능한 세미콜론으로 빗대어지기도 한다.[1]

동기[편집]

모나드는 함수형 프로그래밍에 명령형 프로그래밍을 삽입하는 방법 중 하나이다.[2] 예외 처리와 함수의 부작용을 지원하지 않는 순수한 함수형 언어에서

  1. 함수가 두 가지 이상의 일을 하게 만들고
  2. 두 가지 이상의 일을 표현하는 하나의 자료형 정의하고
  3. 그렇게 만들어진 새로운 자료형을 반환하는 함수를 합성하는 법을 정의하는 데 모나드가 사용되었다.[4] 대표적인 용법으로 입출력이 있다.

그러나 모나드의 쓰임새는 명령형 프로그래밍이나 입출력을 하는 데 제한되지 않는다. 예를 들어 연쇄된 연산을 간략화하거나 복잡한 상태를 숨기고 로그를 남기는 데 쓰일 수 있다. [1] 리스트 또한 모나드로 해석될 수 있다. [5] 모나드는 훨씬 일반적인 개념이며, 범주론에서 모나드가 어디에나 존재하듯이 컴퓨터 과학에 있어서 어디에나 존재한다고 할 수 있다.[2]

정의[편집]

프로그래밍에서의 모나드는 자료형 생성자, 단위 함수, 결속 연산으로 구성된다. 이 요소는 수학에서의 모나드에 있어서의 클라이슬리 순서쌍이라 불리는 세 요소에 대응한다.

  1. 자료형 생성자는 내부 준동형 함자에 해당되며, 기반이 되는 자료형에서 모나드 자료형을 얻는 방식을 서술한다. 하스켈에서 M이 모나드의 이름이고 t가 자료형일때, M t가 해당 자료형의 모나드 자료형이 된다.
  2. 단위 함수는 항등 자연 변환에 해당되며, 기반이 되는 자료형의 값을 모나드 자료형의 값으로 바꾸는 함수이다. 하스켈에서 단위 함수는 return이라 불리며 자료형은 다형성 자료형 t → M t이다.
  3. 결속 연산은 합성 자연 변환에 해당된다. 하스켈에서 중치형 연산자 >>=으로 표현되며 자료형은 다형성 자료형 (M t)→(t→M u)→(M u)이다. 이를 해석하면
    1. 모나드 자료형의 값과
    2. 기반 자료형의 값을 다른 모나드 자료형의 값으로 바꾸는 함수를 받아
    3. 다른 모나드 자료형의 값을 반환하는 함수라고 할 수 있다.

또, 모나드는 모나드 규칙을 만족시켜야 하며,[6] 이는 범주론의 모나드에서의 두 규칙에 대응한다.

  • 단위 함수는 결속 연산의 항등원으로 작용해야 한다. 하스켈을 예로 들면
    • (return v) >>= f f v,
    • m >>= return m이어야 한다.
  • 결속 연산은 결합법칙을 만족시켜야 한다. 하스켈을 예로 들면
    • (m >>= f) >>= g m >>= ( \x -> (f x >>= g) )이어야 한다.

모나드 합성 연산자 >=>[편집]

결속 연산은 합성 연산자 >=>로 대체될 수 있으며, (f >=> g) x (f x) >>= g로 정의된다. 이 경우 모나드 규칙은

  • return >=> g g
  • f >=> return f
  • (f >=> g) >=> h f >=> (g >=> h)

로 표현될 수 있다.

fmap과 join[편집]

단위 함수와 결속 연산을 통해 모나드를 정의하는 것 이외에도, 단위 함수와 다른 두 함수를 이용해 모나드를 정의할 수 있다. 이 두 연산은 하스켈에서 fmapjoin이라 불린다. fmap의 자료형은 (t → u) → M t → M u이며, 기반 자료형간의 함수를 모나드 자료형에 맵핑하는 의미를 지닌다. join의 자료형은 M (M t) → M t이며 두 단계인 모나드 자료형을 한 단계의 모나드 자료형으로 평탄화하는 의미를 지닌다.

단위 함수와 결속 연산에 의한 정의와 단위 함수와 fmap, join에 의한 정의 사이에는 다음과 같은 관계가 성립한다.

fmap f m = m >>= (return . f)
join n = n >>= id

m >>= g      join (fmap g m)

do 표기법[편집]

결속 연산>>=을 프로그램에 직접 쓰는 것이 자연스러울 때도 있지만, 명령형 언어의 생김새를 닮은 표기법을 쓰는 경우가 많다. 하스켈에서는 do를 이용해 표기하며, OCaml에서는 perform을 쓴다. F#에서는 계산 식[7], 스칼라 (프로그래밍 언어)에서는 for 컴프리헨션이라고 한다. 하스켈의 컴파일러는 do 표기법을 결속 연산을 이용한 표현으로 번역하며, 그 규칙은 다음과 같다.[8]

do { x } = x

do { x ; <stmts> }
  = x >> do { <stmts> }
 
do { v <- x ; <stmts> }
  = x >>= \v -> do { <stmts> }

do { let <decls> ; <stmts> }
  = let <decls> in do { <stmts> }

이 때 >>x >> y = x >>= (\_ -> y)로 정의되며, x를 실행한 다음 그 결과를 버리고 y를 실행하여 그 결과를 취하는 것으로 이해할 수 있다.[8]

각주[편집]

  1. O'Sullivan, Bryan; Goerzen, John; Stewart, Don. Real World Haskell. O'Reilly, 2009. ch. 14.
  2. “monad (in computer science)”. 《nLab》 (영어). 
  3. Lippert, Eric. “Monads, part one”. 2013년 9월 6일에 확인함. 
  4. “Why do we need monads?”. 《Stack Overflow》. 2018년 8월 2일에 확인함. 
  5. Miran Lipovača (2011년 4월 15일). 〈12. A Fistful of Monads〉. 《Learn You a Haskell for Great Good!》. no starch press. ISBN 978-1593272838. 2018년 8월 2일에 확인함. 
  6. “Monad laws”. 《HaskellWiki》. haskell.org. 2011년 12월 11일에 확인함. 
  7. “계산 식(F#)”. 2018년 8월 10일에 확인함. 
  8. “Monads as computation”. 《HaskellWiki》. haskell.org. 2018년 8월 10일에 확인함.