2014-10-31 2 views
8

데이터 유형이 A 인 것으로 가정합니다. 예를 들어, AIdentity이라고 가정 할 수 있습니다.동일한 도메인에서 신청자의 기능에 대한 적용 인스턴스

지금은 다른 일 A에서 "변화"에 해당하는 새로운 데이터 유형 :

두 인수를 적용 새로운 변화를 만들어 내가 (B a)의 사소한 실용적 인스턴스를 정의 할
data B a b = B (A a -> A b) 

그 후 입력 및 <*>이 충분히 간단한 공식화 < *> A.의 실용적 인스턴스

의 정의를 사용

,

그러나 나는 (-> a)이 Applicative Functor라는 사실을 사용하여 직접 작성하는 간단한 방법이 있어야한다고 생각합니다.

instance Functor (B a) where 
    fmap f (B xtrans) = B $ (fmap f) <$> xtrans 

실용적 인스턴스를 정의하는 유사 간단한 방법이 있나요 : 내가 마음에 무엇을, 해당 펑터 인스턴스의 내 정의를 고려의 샘플로

?

답변

12

대략 Applicative에 관한 깔끔한 사실 중 하나는이 클래스가 컴포지션으로 닫혀 있다는 것입니다. 당신은 Data.Functor.Compose에서 다음을 얻을 수 있습니다 :

newtype Compose f g a = Compose { getCompose :: f (g a) } 

instance (Functor f, Functor g) => Functor (Compose f g) where 
    fmap f (Compose fga) = Compose (fmap (fmap f) fga) 

instance (Applicative f, Applicative g) => Applicative (Compose f g) where 
    pure a = Compose (pure (pure a)) 
    Compose f <*> Compose x = Compose $ (<*>) <$> f <*> x 

당신이 가지고 (->) aApplicative 인스턴스가, 이것이다 :

이제
instance Applicative ((->) r) where 
    pure = const 
    ff <*> fa = \r -> let f = ff r 
          a = fa r 
         in f a 

,의는 Compose ff <*> Compose fa :: Compose ((->) (A a)) A b을 확장하자 (일부 단계는 생략) :

Compose ff <*> Compose fa 
    == Compose $ (<*>) <$> ff <*> fa 
    == Compose $ \r -> let f = ff r 
          a = fa r 
         in f <*> a 

그럼 당신이하는 일은 효과적으로 (->) (A a)A의 구성입니다. .

+1

질문에서 'B a b'가 '유형 B a = 작성 ((->) (A a)) A'와 동일하다고 말하는 것이 맞습니까? –

+0

@ChristianConkle : 예. –

7

아마도?

(B ftrans) <*> (B xtrans) = B ((<*>) <$> ftrans <*> xtrans) 
2

Luis Casillas의 대답을 피기 백하십시오. B이 문자 그대로 작동하는 데이터 유형 인 경우 Compose ((->) (A a)) A을 사용하면됩니다. 데이터 생성자의 유형은 Compose :: (A a -> A b) -> Compose ((->) (A a)) A b입니다.

유형 동의어 : type B a = Compose ((->) (A a)) A을 사용할 수도 있습니다.

Compose, Product, Sum 및 친구들과 함께 재미있게 스무 싱 펑터를 만들 수 있습니다.

관련 문제