2014-10-07 4 views
18

내가 읽는 중 하스켈을 배우십시오 그리고 이미 적용 사례를 다루었으며 이제는 단서가 있습니다. 나는 둘 다 이해하는 데 아무런 문제가 없다. 비록 실제로 응용에서 유용한 것을 찾았지만 monoid는 그렇지 않다. 그래서 저는 하스켈에 대해 무언가를 이해하지 못한다고 생각합니다.모노로이드의 실제 사용은 무엇입니까?

먼저 Applicative을 말하면 '컨테이너'에 대한 다양한 작업을 수행하기 위해 통일 구문과 같은 것을 만듭니다. 그래서 우리는 Maybe, 목록에 대한 작업을 수행하기 위해 정상 기능을 사용할 수 있습니다, IO, 기능 (? 내가 말한해야 모나드는 아직 모나드를 모르는) :

λ> :m + Control.Applicative 
λ> (+) <$> (Just 10) <*> (Just 13) 
Just 23 
λ> (+) <$> [1..5] <*> [1..5] 
[2,3,4,5,6,3,4,5,6,7,4,5,6,7,8,5,6,7,8,9,6,7,8,9,10] 
λ> (++) <$> getLine <*> getLine 
one line 
and another one 
"one line and another one" 
λ> (+) <$> (* 7) <*> (+ 7) $ 10 
87 

그래서 실용적는 추상화입니다. 나는 우리가 그것 없이는 살 수 있다고 생각하지만 그것은 명확하게 아이디어를 표현하는 데 도움이된다.

이제는 Monoid을 살펴 보겠습니다. 또한 추상화와 매우 단순한 것입니다. 그러나 그것은 우리에게 도움이됩니까? 더 명확 일을하는 방법이 있음을이 책에서 모든 예를 들어이 분명한 것 같다 :

λ> :m + Data.Monoid 
λ> mempty :: [a] 
[] 
λ> [1..3] `mappend` [4..6] 
[1,2,3,4,5,6] 
λ> [1..3] ++ [4..6] 
[1,2,3,4,5,6] 
λ> mconcat [[1,2],[3,6],[9]] 
[1,2,3,6,9] 
λ> concat [[1,2],[3,6],[9]] 
[1,2,3,6,9] 
λ> getProduct $ Product 3 `mappend` Product 9 
27 
λ> 3 * 9 
27 
λ> getProduct $ Product 3 `mappend` Product 4 `mappend` Product 2 
24 
λ> product [3,4,2] 
24 
λ> getSum . mconcat . map Sum $ [1,2,3] 
6 
λ> sum [1..3] 
6 
λ> getAny . mconcat . map Any $ [False, False, False, True] 
True 
λ> or [False, False, False, True] 
True 
λ> getAll . mconcat . map All $ [True, True, True] 
True 
λ> and [True, True, True] 
True 

그래서 우리는 몇 가지 패턴을 발견하고 새로운 형태의 클래스를 만든이 ... 좋아, 나는 수학을 좋아한다. 그러나 실용적인 관점에서, Monoid의 요점은 무엇입니까? 그것은 아이디어를 더 잘 표현하는 데 어떻게 도움이됩니까?

+2

당신이 실제로 monoids의 힘을 보여주는 몇 가지 고급 소재를 파고 싶다면 [finger trees] (http://www.cs.ox.ac.uk/ralf.hinze/publications/FingerTrees.pdf)를 확인하십시오.) ('Data.Sequence' 뒤의 엔진). 나는 지금 당장 생각할 수없는 간단한 예제가 있다고 확신한다. – luqui

+4

나는이 우수한 [Dan piponi] (http://blog.sigfpe.com/2009/01/haskell- monoids-and-their-uses.html) 기사를 살펴 보도록 권합니다. – Sibi

+0

관련이 있지만 중복 질문 : [Data.Monoid의 모든 newtype 래퍼의 실제 가치는 무엇입니까?] (http://stackoverflow.com/questions/22080564/whats-the-practical-value-of-all-those- newtype-wrappers-in-data-monoid) – AndrewC

답변

25

가브리엘 곤잘레스 (Gabriel Gonzalez)는 블로그에서 왜 신경 써야하는지에 대한 훌륭한 정보를 썼습니다. here (및 this 참조)을 읽을 수 있습니다.

확장 성, 아키텍처 & API의 디자인에 관한 내용입니다.

가 "네트워크"또는 B 형의 "토폴로지"

문제로 발생하는 A 형의 함께 몇 가지 구성 요소를 결합 : 아이디어는 말한다 "기존의 아키텍처"가 있다는 것입니다 이런 종류의 디자인은 프로그램의 확장에 따라 리팩터링 할 때 지옥도 마찬가지입니다.

그래서 디자인이나 도메인을 개선하기 위해 모듈 A를 변경하려고합니다. 아,하지만 A 모듈에 의존하는 & C 모듈이 망가졌습니다. 너는 B를 고친다. B가 또한 C의 기능 중 일부를 사용 했으므로 이제 B가 다시 부러졌습니다. 그리고 저는 이것을 영원히 계속할 수 있습니다. 그리고 OOP를 사용한 적이 있다면 그렇게 할 수 있습니다.

그런 다음 가브리엘은 "하스켈 아키텍처"부르는있다 : 그 치환기 부분에서

하는 동일한 유형 A의 새로운 구성 요소를 생성하기 위해 함께 A 형의 여러 구성 요소를 결합, 문자의 구별을

이렇게하면 문제도 우아하게 해결됩니다. 기본적으로 모듈을 겹치거나 확장하지 마세요.
대신 결합하십시오.

이제는 "여러 개의 X가 있으므로 그 유형을 만들어 합집합을 나타내 보겠습니다."라고 말하면 "여러 개의 X가 있으므로 X에 결합합시다."라고 말하면 좋습니다. 또는 간단한 영어로 : "처음부터 조합 가능한 유형을 만들어 보겠습니다." (당신은 monoids가 아직 숨어 있다는 것을 느끼나요?).

웹 페이지 나 응용 프로그램의 양식을 만들고 싶다고하고 개인 정보가 필요했기 때문에 만든 "개인 정보 양식"모듈을 가지고 있다고 가정 해보십시오. 나중에 당신은 또한 당신이 "Change Picture Form"을 그렇게 빨리 작성해야한다는 것을 알았습니다. 그리고 이제 저는 그것들을 결합하고 싶습니다. 그래서 "개인 정보 & 그림"모듈을 만들어 봅시다. 그리고 실생활에 확장 가능한 응용 프로그램에서는 이것이 가능할 수도 있고 불가능할 수도 있습니다. 아마하지하지만 형태는 설명하기 위해, 당신은 그래서 당신은 "개인 정보 & 변경 사진 & 변경 상태 &가 관리 & 암호 변경으로 끝날 것이다 작성하고 구성 할 필요가 친구 & 관리 위시리스트 &보기 변경 설정 & 저를 더 이상 연장하지 마십시오 &하시기 바랍니다 & 중지하십시오! & 중지 !!!! " 기준 치수. 이것은 꽤 아니므로 API에서 이러한 복잡성을 관리해야합니다. 아, 그리고 만약 당신이 아무것도 바꾸고 싶다면 - 아마 의존성이 있습니다. 그래서 .. 그래 .. 지옥에 오신 것을 환영합니다. 따라서 우리는 필요가 없습니다,

이 추상화가 확장 무제한을 그들은 항상 결합 가능을 보존하기 때문에 : 이제

의 다른 옵션을 살펴 보자하지만, 먼저는 우리를 안내 할 것입니다 때문에의이 혜택을 살펴 보자 상단에 더 추상화 을 추가합니다. 이것이 하스켈을 배워야하는 이유 중 하나입니다. 을 플랫 아키텍처로 구축하는 방법을 배웁니다.

"개인 정보 양식"/ "그림 양식 변경"모듈을 만드는 대신, 여기에있는 것들을 구성 가능하게 만들 수 있다면 그만 두십시오. 음, 우리는 단지 "양식"을 만들 수 있습니다, 그렇죠? 너무 추상적 일 것입니다.
그러면 원하는 모든 것을 하나씩 구성하고 함께 결합하여 다른 양식과 마찬가지로 하나의 양식을 얻을 수 있습니다.

그래서 두 가지 형태를 취하여 하나의 형식을 얻는 열쇠 때문에 더 이상 복잡한 나무를 얻지 못합니다. 그래서 Form -> Form -> Form. 이미 명확하게 볼 수 있듯이이 서명은 mappend의 인스턴스입니다. 그렇게 도전이 아니다 형태의

대체하고, 기존의 아키텍처는 아마 다음 a -> b -> c 다음 c -> d -> e과 같을 것이다 ... 이제

; 문제는 실제 응용 프로그램에서이 문제를 해결하는 것입니다. 그리고 그 일을하기 위해서 당신이 할 수있는 한 최대한 물어보십시오 (보시다시피 돈을 지불하기 때문에). 어떻게이 개념을 구성 가능하게 만들 수 있습니까? 그리고 monoids는 그것을 달성하는 간단한 방법이므로 (우리가 간단하게 원함) 먼저 자신에게 물어보십시오.이 개념은 어떻게 monoid입니까?

Sidenote : 고맙게도 하스켈은 유형을 기능 언어 (상속 없음)이므로 확장하지 않을 것입니다. 그러나 무언가를위한 유형, 무언가를위한 또 다른 유형, 그리고 두 유형 모두를 필드로 사용하는 세 번째 유형을 만드는 것이 여전히 가능합니다. 이것이 구성 용인 경우 - 피할 수 있는지 확인하십시오.

+2

+1 멋진 기사와 답변! – Mark

+1

실행중인 예제로 특별히 'Monoid'를 사용하는 [this post] (http://www.haskellforall.com/2014/07/equational-reasoning-at-scale.html)를 언급 할 수도 있습니다. –

6

으로 태그를 지정하면 정수를 곱할 의사가 있음을 나타냅니다. 함께 추가 할 Sum으로 태그를 지정합니다.

다음 두 가지 모두에서 같은 mconcat을 사용할 수 있습니다. 예 : in Foldable 하나의 foldMap은 포함하는 구조에 대해 접히는 개념을 표현하는 반면, 특정 모노 노드의 방식으로 요소를 결합합니다.

9

좋아, 나는 수학을 좋아한다. 그러나 실용적인 관점에서 Monoid의 요점은 무엇입니까? 그것은 아이디어를 더 잘 표현하는 데 어떻게 도움이됩니까?

API입니다. 간단한 것. 지원 유형 :

  • 가 추가 작업을 유형

많이 갖는 제로 소자

  • 을 갖는 이들 동작을 지원한다. 따라서 작업 이름과 API를 사용하면 사실을보다 명확하게 파악하는 데 도움이됩니다.

    API는 코드 재사용 및 개념 재사용을 가능하게 해주기 때문에 유용합니다. 더 나은 유지 보수가 가능한 코드를 의미합니다.

  • 5

    매우 간단한 예는 foldMap입니다. 그냥이 하나의 함수에 다른 monoids 연결하여, 당신은 계산할 수 있습니다 :

    • firstlast 요소,
    • sum 또는 (이 또한 평균 등의) 요소의 product
    • 체크 경우 all 요소 또는 any 갖는 주어진 속성
    • 최대 또는 최소의 요소를 계산
    • ,
    • 나열 등 012,391,254,398,952 (a 컬렉션 요소 매핑, 문자열, Text, ByteString 또는 ByteString Builder)를 결합하여 모두 연결합니다.

    더욱이, monoids가 작성 가능하다 : ab monoids이 경우, 그렇게 (a, b)이다. 따라서 한 패스에서 여러 개의 다른 모노도 값을 쉽게 계산할 수 있습니다 (예 : 요소 및 요소의 평균을 계산할 때 합계 및 곱과 같음).

    당신이 foldr 또는 foldl를 사용 monoids없이이 모든 작업을 수행 할 수 있지만, 그것은 종종 덜 효과적 훨씬 더 복잡하고도있다 : 예를 들어, 당신은 균형 이진 트리가 있고 최소 및 최대 요소를 찾으려면, foldr (또는 둘 다 foldl)으로 효과적으로 수행 할 수 없으며, 하나의 경우에 항상 O (n)이고, foldMap과 적절한 모노도를 사용하는 경우는 O (로그 n)입니다. 두 경우 모두입니다.

    그리고 이것은 단지 하나의 기능이었습니다 foldMap!다른 많은 흥미로운 응용 프로그램이 있습니다. 이를 줄이기 위해서는 exponentiation by squaring이 힘을 계산하는 효율적인 방법입니다. 그러나 사실 컴퓨팅 능력과 관련이 없습니다. 모든 모노oid에 대해 구현할 수 있으며 <>O (1) 인 경우 효율적인 계산 방법은 n-x <> ... <> x입니다. 그리고 갑자기 효율적인 행렬 지수 연산을 수행하고 n -th Fibonacci numberO (log n) 곱셈으로 계산할 수 있습니다. times1p세미 그룹으로 보아라.

    도 참조하십시오. Monoids and Finger Trees.