2016-10-19 1 views
7

자바에서 함수 인스턴스를 구현하여 ApplicativeMonad에 대한 이해를 높이려고합니다. 하스켈에 대한 나의 지식은 제한적이며 내 질문이 전혀 의미가 없기를 바랍니다. 여기함수 인스턴스의 bind/>> =를 해석하는 방법은 무엇입니까?

자바 스크립트에 Functor, ApplicativeMonad typeclasses에 대한 fmap, <*>>>=의 내 구현은 다음과 같습니다

:

const fmap = f => g => x => f(g(x)); // B combinator 
const apply = f => g => x => f(x) (g(x)); // S combinator 
const bind = f => g => x => g(f(x)) (x); // ? 

내가 bind가 하스켈 구현의 정확한 번역인지 확실하지 않다

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

instance Monad ((->) r) where 
f >>= k = \ r -> k (f r) r 

을 제공한다면 bind이 정확한지를 어떻게 해석합니까? Applicative은 효과적인 계산을 순서대로 처리 할 수 ​​있음을 알고 있습니다. 또한 Monad은 이전 결과의 결과에 따라 다음 효과를 결정할 수 있음을 알고 있습니다.

  • apply :

    나는 시퀀스 (자바 스크립트의 열망 평가 순서) 볼 수 있습니다 f(x) ... g(result of f) : f(x) ... g(x) ... lambda(result of g) ...을 lambda

  • bind의 결과 ... lambda(x) ... 그러나 lambda

의 결과는 bind 재미 ction은 꽤 이상하게 보입니다. fg이 다른 방법으로 중첩 된 이유는 무엇입니까? 이 구현에 반영된 특정 Monad 동작 (이전 효과에 따라 다음 효과를 결정)은 어떻게됩니까? 사실 g(f(x)) (x)은 반전 된 인수가있는 함수 구성과 같습니다. 여기서 g은 이진 함수입니다.

단항 및 이진 함수로 apply/bind을 적용하면 동일한 결과가 나타납니다. 이것은별로 의미가 없습니다.

+0

'bind' (JS에서'chain'으로 알려짐)의 유용한 응용 프로그램에 대해서는 [this example] (http://stackoverflow.com/q/40026018/1048572)을보십시오 – Bergi

답변

5

함수에 대한 모나드 인스턴스의 값은 고정 유형 r에 대해 r -> a 유형입니다. (a -> (r -> b))(>>=)에 주어지면 현재 값 (함수 r -> a)에서 주어진 결과를 반환 할 다음 함수를 선택할 수 있습니다. f r 유형은 a이고 k (f r) 유형은 r -> b이며 적용 할 다음 기능입니다.

코드에서 g(f(x))r 유형의 단일 인수가 필요한 함수입니다. bind의 호출자는 이전 기능에 의해 리턴 된 값에 기초하여이 기능을 선택할 수있다.

var inc = x => x + 1; 
var f = bind(inc)(function(i) { 
    if(i <= 5) { return x => x * 2; } 
    else { return x => x * 3; } 
}); 

함수는 입력으로서 x 부여되며 inc(x) 예컨대 결과에 기초하여 계산의 다음 단계를 선택할 수 있습니다리의 대답

f(2) //4; 
f(5) //15; 
+0

고마워, 너무 분명하다. 지금! Haskell 관용구를 Javascript로 전송하려고 할 때 종종 같은 문제에 직면합니다. Haskell 관용구에 대한 많은 지식은 구현이나 형식 시그니처뿐만 아니라 애플리케이션에 숨겨져 있습니다. – ftor

+0

이제 다음 계산은 이전 결과에 따라 다르지만이 결과는 완전히 무시됩니다. 이것은'bind'가 일반적으로 작동하는지 또는 당신의 예제에 특정한 방식입니까? 모든 질문에 대해 유감스럽게 생각합니다! – ftor

+0

@ftor - 죄송합니다. 답변이 잘못되어 수정 사항이 잘못되었습니다. 'bind'는'f (x)'만 사용하여 다음 함수를 선택하지만 원래 입력을 제공합니다. – Lee

4

몇 각주 :

그러나, bind 기능은 꽤 이상한 보인다. fg 은 다른 방법으로 중첩 된 이유는 무엇입니까?

bind은 거꾸로 때문에. 특정 예에서,

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

을 또는 : (>>=) 비교하고 이성을 상실 버전 (=<<) 우리가 (=<<)보다는 때문에 구문 말하는 방법 (>>=), 더 자주 (>>=)을 사용하는 경향이

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

연습에있는 동안 빌려을 그 자체가 잘 파이프 모나드의 종류에 자주 건설에 사용되는, 이론적 인 관점에서 그것을 쓰는 가장 자연스러운 방법입니다. 특히, 평행 및 fmap/(<$>)(<*>)와 차이가 훨씬 더 명백하다 :

(<$>) :: Functor f  => (a -> b) -> f a -> f b 
(<*>) :: Applicative f => f (a -> b) -> f a -> f b 
(=<<) :: Monad f  => (a -> f b) -> f a -> f b 

내가 단항 및 이항 함수와 apply/bind을 적용, 그들은 동일한 결과를 얻을 수 있습니다. 이것은별로 의미가 없습니다.

이는 함수 인스턴스에 대한 우연한 사실입니다. Applicative 이미 그렇게 할 수 있습니다 - "이전 효과"반대로 (이전 결과에 따라 다음 효과를 판단 할 수있는 수단을 제공함으로써

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

MonadApplicative 넘어 :의 측면에서 전문 서명 측을 넣어 보자). 이 경우 효과는 유형이 r 인 주어진 값을 생성하는 함수로 구성됩니다. 이제는 여러 인자 (함수를 반환하는 함수)가있는 함수를 뒤집을 수 있기 때문에 (r -> (a -> b))(a -> (r -> b)) 사이에 큰 차이가 없으므로 (flip은 하나를 다른 것으로 쉽게 변경할 수 있음) (->) r에 대한 인스턴스가 완전히 동일하게됩니다. Applicative 중 하나입니다.

+0

매우 도움이됩니다. 감사합니다! – ftor

+1

@ftor 환영합니다. 내 대답을 다시 살펴보면서 나는 당신의 질문을 너무 빨리 읽음으로써 중요한 혼란을 간과했다는 것을 알아 차렸다.Monad와 Applicative의 차이점은 Monad를 사용하면 "이전의 것에 따른 다음 효과"를 결정할 수 있다는 것입니다. 'Applicative '는 이미 그것을 허용합니다. 'Monad'가 추가 한 것은 이전 * 결과 * (즉, Monad a => a -> m b'의 'a'에 해당하는 functor의 기본 값)의 효과를 결정하는 것입니다. – duplode

관련 문제