2017-01-06 7 views
0

물고기 조작자에 비해 Monads는 연관성을 만족시킵니다. 다음 식을 의미람다 식에서 모나드에 전달 된 매개 변수에 대해 증명할 수있는 것은 무엇입니까?

(람다 식으로) 결합과 같은 번역
(h >=> g) >=> f = h >=> (g >=> f) 

이,

\a -> h a >>=(\b -> g b >>= \c -> f c) = 
\a ->(h a >>= \b -> g b)>>= \c -> f c 

이것은 단항 조성을 이해하는 좋은 방법이다

(a -> h a >>= \b -> g b >>= \c -> f c) = h >=> g >=> f 

모호하다.

그러나 모든 모나드 코드가 람다에 대한 바운드 변수를 분리 된 상태로 유지하는 것은 아닙니다. 예 :

[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch) = 
[(1,'a'),(1,'b'),(2,'a'),(2,'b')] 

"n"은 상위 람다에서 얻은 것입니다.

보다 일반적

a -> g a >>= \b -> f a b 

f는 상기 두 A 및 B에 따라 달라진다. 의 관점에서 위의 정의 F, G, 그리고 (> =>) 내가 잘 이해하지 못하는

\a -> (\x -> g a) >=> f a 

을 제공합니다. 위의 방정식과 일치하지 않아 매우 잘 나타났습니다. 저는 물고기를 근본적인 개념으로 여기에서 봅니다. 그리고 그것이 제가 쓰는 전형적인 모나드와 어떻게 상호 작용하는지 이해하려고 노력하고 있습니다. 위의 내용을 더 잘 이해하고 싶습니다. 이 접근의

한 가지 방법은 내가이 대칭의 종류를 의미한다 생각 목록 식 구문

[ (n,ch) | n <- [1, 2], ch <- ['a', 'b'] ] 

에서 의미를 얻기 위해 노력하는 것입니다.

람다 식과 모나드를 연결하는 멋진 대칭이 있습니까? 아니면 내가 이것에 너무 많이 읽고 있니? 매우 중첩 된 람다 표현에 대한 내 두려움이 잘못되었거나 합리적입니까?

+2

나는이 질문을 전혀 이해하지 못합니다. – melpomene

+0

"직관적으로 중첩 된 람다 간의 미묘한 결합을 두려워합니다." - 당신이 걱정하고있는 것에 대해 좀 더 말해 줄 수 있습니까? – duplode

+0

@duplode 내 편집이 내 걱정을 분명히합니까? – Polymer

답변

5

아니요, 제한이 없습니다. 람다를 묶었 으면 anything을 할 수 있습니다. 이것은 Applicative의 이유 중 하나는 Monad이기 때문에 더 약합니다. (따라서 더 강력한 자유 정리 제한을 제공합니다).

([1,2] >>= \n -> "ab" >>= \ch -> return (n,ch)) 
    ≡ (,) <$> [1,2] <*> "ab" 
    ≡ liftA2 (,) [1,2] "ab" 
    ≈ liftA2 (flip (,)) "ab" [1,2] 

마지막은 실제로 적절한 방정식이 아닙니다. 실용적 법률은 참조 이러한 식에 대한 의견 같은 것입니다 만 보장하지만, 구조 수와는 다릅니다.

Prelude Control.Applicative> liftA2 (,) [1,2] "ab" 
[(1,'a'),(1,'b'),(2,'a'),(2,'b')] 
Prelude Control.Applicative> liftA2 (flip (,)) "ab" [1,2] 
[(1,'a'),(2,'a'),(1,'b'),(2,'b')] 
+0

솔직히 말해서,'f <$> x <*> y'와 'flip f <$> y <*> x'사이의 관계가 적용 법률에 포함된다는 것을 확실히 모르겠다. 그 대칭에 대해 그들이 뭐라 말할 수는 있지만 그 법칙을 제대로 이해하는데 어려움을 겪었습니다. – leftaroundabout

+2

댓글을 대해서는'State'가 <$> F a에서 f '사이의 값의 동일성 반례 <$><*> y' X'및 Y 플립이다 <*> x' - 예를 들어, 'runState ((/) <$> 상태 ((2 *) &&& (3 *)) <*> 상태 ((+4) &&& (빼기 3))) 1은'(1/7, 0)'이지만'runState (flip (/) <$> 상태 ((+4) &&& (3을 빼기)) <*> 상태 ((2 *) &&& (3 *))) 1은'(-4/5, -6)'입니다. – duplode

+1

더 일반적으로,'Applicative' 인터페이스는 그 자체로 효과들 사이의 의존성을 가능하게하지는 않지만, 그것의 존재는 그러한 의존성을 방해하지 않습니다. StateT는 사실상 임의의 의존성을 허용하기 때문에'State'보다 훨씬 더 좋다고 생각합니다. – dfeuer

2

당신이 작성하는 방법을 고려하는 사용자의 편집 ... (>=>)를 사용

\a -> g a >>= \b -> f a b 

은 ... 아무것도 실제로이 경우 손실되지 않습니다를 해결.우리가 첫 번째 인수를 켜는 순간 방정식에서

f >=> g = \x -> f x >>= g 
m >>= f = (const m >=> f)() -- const x = \_ -> x 

, 우려와 관련된 하나입니다 : 다시 걸음을하고 (>=>)(>>=)로 변환 할 수있는 방법을 정확하게 고려하고 반대하는 것이 도움이된다 (>>=)const을 사용하여 (>=>)으로 전달할 수있는 함수로 변환합니다. const m >=> f은 인수를 무시하는 함수이므로 (>>=)을 복구하려면 더미 인수로 ()을 전달하기 만하면됩니다. 그래서, 당신의 예제는 두 번째 방정식을 사용하여 다시 작성할 수 있습니다되고 그건

:

\a -> g a >>= \b -> f a b 
\a -> (const (g a) >=> \b -> f a b)() 
\a -> (const (g a) >=> f a)() 

어느 더미 () 공급의 추가 해트트릭을, 당신은 귀하의 질문에 취득했다 무엇을 제외하고.

2

추가 아이디어 : 모나드는 입력에 따라 효과가 달라질 수 있다는 점에서 가장 일반적입니다. 입력이 a이고 출력이 b 인 모나드 계산 ma -> m b과 같이 쓸 수 있습니다. 이것이 함수이기 때문에, 람다를 사용하여 그러한 계산을 정의 할 수 있습니다. 람다는 자연스럽게 오른쪽으로 확장 될 수 있습니다. 그러나이 일반성은 계산을 당신의 \a -> g a >>= \b -> f a b으로 분석하는 것을 복잡하게합니다.

arrows (적용 functor와 모나드 사이의 공간을 차지함)의 경우 상황이 다소 다릅니다. 일반적인 화살표의 경우 입력은 명시 적이어야합니다. 화살표 계산 arr은 일반적인 유형이 arr a b입니다. 화살표 계산에서 "앞으로"움직이는 입력은 화살표 원형을 사용하여 명시 적으로 거기에 스레드되어야합니다. (화살표는 하나 개의 입력 값을 수용으로 정의되므로) 현재 입력으로 쌍을 취해야 기능 f :

은 예컨대 화살표로

{-# LANGUAGE Arrows #-} 

import Control.Arrow 

bind2 :: (Monad m) => (a -> m b) -> (a -> b -> m c) -> a -> m c 
bind2 g f = \a -> g a >>= \b -> f a b 

를 확장한다. 화살표 do 표기법을 사용하여 우리는 Arrow 프리미티브를 사용하여

bind2A :: (Arrow arr) => arr a b -> arr (a, b) c -> arr a c 
bind2A g f = proc a -> do 
       b <- g -< a 
       c <- f -< (a, b) 
       returnA -< c 

심지어 간단한로 표현할 수 있습니다 : 그래픽

bind2A' :: (Arrow arr) => arr a b -> arr (a, b) c -> arr a c 
bind2A' g f = (returnA &&& g) >>> f 

:

--------------->[ ] 
    \   [ f ]----> 
    \-->[ g ]-->[ ] 

덜 일반적이기 때문에, 화살표는 더 많은 추론 할 수 실제로 실행되기 전에 회로에 대한 정보. 좋은 책은 Understanding arrows으로, 정적 인 부분과 동적 인 부분을 가짐으로써 공간 누출을 피할 수있는 파서를 구성하는 것의 배후에있는 원래의 동기를 설명합니다.