2017-02-15 4 views
3

와 <*>을 적용 :약간 좀 <code>Haskell</code> 코드를보기 시작 발견 우편

foo :: ([a] -> [b]) -> [a] -> [(a, b)] 
let foo = (<*>) zip 

이 어떻게 작동하는지 이해가 안가, apf (a -> b) -> f a하지만 zip 유형 [a] -> [b] -> ([a, b])이다 기대하고있다. f a -> f b[a] -> [b]과 일치하지만 f (a -> b)은 그렇지 않다는 것을 알고 있습니다.

+1

힌트 :'x -> y '를'((->) x) y'라고 씁니다. – leftaroundabout

+2

'ap' (또는'<*>')는 실제로'f (a-> b)'를 기대하고'f a -> f b'를 반환합니다. 그래서'ap'는'[a-> b]'또는'c -> a -> b'까지 가질 수 있습니다. 그래서, 어떤 이진 함수도'zip'처럼 괜찮습니다. – chi

답변

7

손으로 종류를 알아 보겠습니다. 첫째, 관련 표현의 유형은 무엇입니까?

(<*>) :: Applicative f => f (a -> b) -> f a -> f b 
zip :: [a] -> [b] -> [(a, b)] 

지금, 우리는 (<*>)에 첫 번째 인수의 종류에 zip의 유형을 통합 할 필요가있다.

Applicative f => f (a -> b) 
       [c] -> [d] -> [(c, d)] 

첫째, f 것입니다 :의는 관련이없는 a들과 b의 이름을 변경하자? 어떤 응용 프로그램을 사용하고 있습니까? 아래쪽 절반의 유형은 함수이므로 은 ((->) [c])이거나 "c의 목록을 입력으로 사용하는 함수"여야합니다. 우리가 그 일을하고 나면, 우리는 볼 수 있습니다 :

f ~ ((->) [c]) 
a ~ [d] 
b ~ [(c, d)] 

을 이제 우리는 일치하는 유형을 가지고 있음을, 우리는 기능 (<*>)의 정의를 찾아 볼 수 있습니다 :

instance Applicative ((->) a) where 
    pure = const 
    (<*>) f g x = f x (g x) 

여기 f에 대한 zip을 대체하고, 람다로 재 작성 수익률 :

(<*>) zip = \g x -> zip x (g x) 

그래서,이 [a] -> [b]와에서 기능을 필요로을 호출하고 입력 목록에 함수를 호출 한 결과를 압축합니다.

기계적으로는 의미가 있지만 그 이유는 무엇입니까? 모든 일반적인 이해가 손으로 모든 것을 다 처리하지 않고도이 결론을 이끌 수 있습니까? 나는 이것에 대한 내 자신의 설명이 유용 할 것이 확실치 않으므로 어떤 일이 일어나는지 이해하지 못한다면 ((->) t)에 대한 인스턴스를 스스로 공부하고 싶을 수도 있습니다. 그러나 그것이 유용 할 경우에, 여기 handwavy expanation이 있습니다.

((->) t)의 Functor, Applicative 및 Monad 인스턴스는 Reader t : "t 유형의 값에 암시 적으로 액세스하는 함수"와 동일합니다. (<*>)은 Applicative 래퍼 내부에서 함수를 호출하는 것에 관한 것으로, 함수의 경우 두 개의 인수를 갖는 함수입니다. "암시 적"인수가 f에 전달되어 다른 함수가 만들어지며 암시 적 인수를 g에 전달하여 얻은 값으로 해당 함수를 호출합니다. 따라서 (<*>) f은 일부 f에 대해 "다른 기능을 제공하고 값은 x이고 xf과 다른 함수에 모두 전달합니다."