2012-10-26 5 views
7

기능이 모나드 일 수있는 방법을 이해하는 데 어려움이 있습니다. 미란 Lipovača says이 나를 혼란하게 대해모나드 인스턴스로서의 기능

instance Monad ((->) r) where 
    return x = \_ -> x 
    h >>= f = \w -> f (h w) w 

심지어 어떤 :

기능 (->) rControl.Monad.Instances의 선언에 따라 모나드 인, >>=의 구현이 조금 애매 보인다

하지만, 실제로는 이 아닙니다. 함수에 모나드 값을 공급하기 위해 >>=을 사용하면 결과는 항상 모나드 값입니다. 따라서이 경우 다른 함수에 함수를 공급하면 결과도 함수입니다. 결과는 람다로 시작하는 이유는 입니다. >>=의 구현은 항상 모나드 값에서 결과를 분리 한 다음 해당 결과에 함수 f를 적용했습니다. 똑같은 일이 여기 발생합니다. 함수에서 결과를 얻으려면 함수에 적용해야합니다. 따라서 함수를 사용하여 함수의 결과를 얻은 다음 f를 적용합니다. f는 모나드 값을 반환하는데, 이 우리 함수의 함수이므로, 우리는 이것을 w에 적용한다. -> (A -> MB) -> 메가

그래서 h과 같이 입력했는지 걸릴 (>> =) :: 엄마 :

의 유형 서명은 (>> =)이있다 m af(a -> m b)이다. 함수가 m a 인 경우 a 값을 반환합니까? 또는 a 유형을 가지고있는 다른 것을 반환합니까? h의 비 모나드 값이 f에 공급되는 경우

은, 우리가 얻을 : F (시간 w) 잘 보인다. f은 하나의 함수이고 유일한 인수를 사용 했으므로 이미 값입니다. 모나드 함수이기 때문에이 값은 모나드 값이기도합니다. 그렇다면 왜 다른 값 w이 필요합니까? w ~ f something을 모나드가 아닌 것으로 만들지 않습니까? 즉, 더 이상 기능이 아닌 것입니까? 아니요. 또한 f somethingh이 같은 인수 인 w을 사용하고 다른 값 유형 (m am b)을 반환하는 이유를 이해할 수 없습니다.

답변

10

첫째, 여기에 (>>=)의 유형입니다 일부 불필요한 괄호 :

(>>=) :: (r -> a) -> (a -> r -> b) -> r -> b 

하는 시점에서 무슨 일이 벌어지고 있는지보고 더 쉽게해야한다 : 유형 a의 무언가를 얻기 위해 첫 번째 인수로 주어집니다 (유형 r의) 세 번째 인수 한 후 결과와 세 번째 인수 모두 그 두 번째 인수에 부여되어 b 유형의 최종 결과를 얻습니다.

따라서 Monad으로 표시된 ((->) r)은 모나드의 모든 값에 대한 추가 함수 인수를 나타내며 모나드 값이 결합되면 단일 "여분"인수가 복제되어 각 입력 값에 제공됩니다. 기본적으로 모나드 값에 대한 "읽기 전용 전역 환경"을 만듭니다. 이 해석은 Reader 모나드로 명시 적으로 제공됩니다.이 모나드는 ((->) r) 주위의 래퍼입니다.

+0

감사합니다. 모든 것이 분명하다! – amemus

5

그것은보고이 모나드를 이해하는 것이 아마도 쉽게 무엇을 join, 모나드가 동등하게 fmapjoin 대신 >>=을 사용하여 정의 할 수 있기 때문이다.

join의 일반 형식은 Monad m => m (m b) -> m b 유형이므로 "2 계층"모나드 값을 취하여 하나의 계층으로 잘라냅니다.

함수 monad의 경우 m ~ (a ->)이므로 join의 형식은 (a -> a -> b) -> (a -> b)이므로 두 개의 인수를 사용하고 하나만 사용하는 함수를 반환합니다.

join :: (a -> a -> b) -> (a -> b) 
join f = \x -> f x x 

자세히 알 수 있듯이 인수가 중복됩니다.

마찬가지로 함수의 fmap은 함수의 구성이며 returnconst입니다.

>>=을 이해하려고 시도하는 것보다이 방법을 이해하는 것이 훨씬 쉽다고 생각합니다. m 전문 ((->) r)에와 지금

(>>=) :: (Monad m) => m a -> (a -> m b) -> m b 

, :

(>>=) :: ((->) r) a -> (a -> ((->) r) b) -> ((->) r) b 

모든 기능 화살표 중위로 재 작성 : 제거

(>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b) 

+0

인스턴스를 개념적으로 이해하는 데 유용하지만'do = '표기법의 각 행이 해당 모나드를 의미하는지 여부를 파악하기 위해서는 여전히'>> ='의 동작을 이해해야합니다. –

+0

@ DanBurton :이 경우에는 실제로 "Applicative"인스턴스가 "환경"이 항상 첫 번째 인수이고 "Monad"인스턴스가 매개 변수 순서와 동일하므로 설명하고 이해하기가 가장 쉽다고 생각합니다. –