2016-10-27 2 views
6

:: (Foldable t, Num a) => t a -> (a, a) 형식의 fold ((,) <$> sum <*> product) 코드 조각을 발견하고 완전히 잃어 버렸습니다.하스켈 : 유형 f가 실제로 의미하는 것은 무엇입니까?

나는 그것이 무엇을하는지 알고 있지만, 어떻게해야할지 모른다. 그래서 저는 ghci에서 작은 조각으로 나누려고했습니다 :

모든 것이 정상적이고 기본적인 것입니다.

λ: :t (,) <$> sum 
(,) <$> sum :: (Foldable t, Num a) => t a -> b -> (a, b) 

그리고 나는 다시 분실하고 ...

나는 f a으로 t a -> a를 켜졌지만 어떻게 수행하는 것은 나에게 신비 마법 일어나고 있다는 것을 참조하십시오. (sumFunctor의 경우에도 인스턴스가 아닌!) 난 항상 f aa을 포함 상자 f의 일종이지만 의미가 매우 깊은 것 같습니다 것을 생각

. 이 기능을 위해 기본적으로 구현, 물론

newtype Reader r = Reader (r -> a) 

, 하스켈, 그래서이 :

+1

'<$>는'단지 중위되고있는'fmap' :'<$> X = fmap 함수 f를 x' 바. – chepner

답변

5

당신의 예에서 펑 f는 다음과 같이 정의 된 소위 "리더 펑"입니다 런타임시 랩핑 또는 언 래핑.

대응 FunctorApplicative 인스턴스

는 다음과 같다 :

방식
instance Functor f where 
    fmap :: (a -> b) -> (r -> a)_-> (r -> b) 
    fmap f g = \x -> f (g x) -- or: fmap = (.) 

instance Applicative f where 
    pure :: a -> (r -> a) -- or: a -> r -> a 
    pure x = \y -> x -- or: pure = const 
    (<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b) 
    frab <*> fra = \r -> frab r (fra r) 

는 리더 펑은 타입을 생성하는 컨텍스트 r를 갖는 다른 모든 펑 등 역시 "박스"이다 a .

그럼 (,) <$> sum 살펴 보자 :

:t (,) :: a -> b -> (a, b) 
:t fmap :: (d -> e) -> (c -> d) -> (c -> e) 
:t sum :: Foldable t, Num f => t f -> f 

우리는 지금 t fb -> (a, b)ca ~ f, ed 유형을 전문으로 할 수 있습니다. 이제 우리가 얻을 :

:t (<$>) -- spcialized for your case 
:: Foldable t, Num f => (a -> (b -> (a, b))) -> (t f -> f) -> (t f -> (b -> (a, b))) 
:: Foldable t, Num f => (f -> b -> (f, b)) -> (t f -> f) -> (t f -> b -> (f, b)) 

이 기능을 적용 :

GHC 말한다 정확히 무엇
:t (,) <$> sum 
:: Foldable t, Num f => (t f -> b -> (f, b)) 

.

+1

Nitpick :이 경우에는 "뒤에서"랩핑과 언 래핑이 없습니다. 언급 한 인스턴스는 노출 된 함수에 사용할 수 있으므로 '판독기'래퍼 (주로 선명도와 가독성을 제공하기 위해 존재 함)는 여기에 포함되지 않습니다. – duplode

+0

@duplode 그래, 나는 그것이 명확하지 않은 것을 본다. 나는 그것을 추가 할 것이다, 고마워. – ThreeFx

2

짧은 대답은 f ~ (->) (t a)입니다. 이유를 확인하려면 sum의 형식 시그니처를 약간 재정렬하십시오. 삽입 연산자 대신 접두사 연산자로 ->을 사용하십시오.

sum :: (Foldable t, Num a) => (->) (t a) a 
           ~~~~~~~~~~ 
            f 
일반적

, (->) r 모든 인수 형식 r 대한 펑이다.

fmap :: (a -> b) -> f a -> f b 
    :: (a -> b) -> ((->) r) a -> ((->) r) b 
    :: (a -> b) -> (r -> a) -> (r -> b) 

이 컴포지션 유형 서명이며, 구성은 다음과 같습니다

instance Functor ((->) r) where 
    fmap = (.) 

은 여기 f에 대한 fmap의 종류에 ((->) r)를 연결하여 (.)fmap에 대한 유일하게 가능한 구현 것을 보여 쉽게 이 형식 시그니처가있는 고유 함수. Data.Functor 이후


, 그것은 참으로, 결과 유형인지 확인하는 지루한하지만, 비교적 간단한 일이다, 우리가 여기에서

(,) <$> sum == fmap (,) sum 
      == (.) (,) sum 

을 가지고 fmap의 중위 버전으로 <$>을 정의 (Foldable t, Num a) => t a -> b -> (a, b). 우리는

(b' -> c') -> (a' -> b') -> (a' -> c') -- composition 
b' -> c' ~ a -> b -> (a,b)    -- first argument (,) 
a' -> b' ~ t n -> n      -- second argument sum 
---------------------------------------------------------------- 
a' ~ t n 
b' ~ a ~ n 
c' ~ a -> b -> (a,b) 
---------------------------------------------------------------- 
a' -> c' ~ t a -> b -> (a,b) 
관련 문제