2013-08-05 4 views
20

내 코드가 FunctorApplicative과 같은 추상화를 사용하지만 이점 유형이 (* -> *) -> * 인 경우에 도움이되는 상황이 발생했습니다. 더 높은 kinded 펑터를 정의하는 것은이종류 (* -> *)에 대한 펑크와 응용 프로그램 -> *

class HFunctor f where 
    hfmap :: (forall x. a x -> b x) -> f a -> f b 

처럼 RankNTypes으로 수행하지만 Applicative의 높은 종류의 버전은 조금 까다 롭습니다 수 있습니다. 이것은 내가 가지고 올 수있는 최선입니다 :

class HFunctor f => HApplicative f where 
    hpure :: (forall x. a x) -> f a 
    (<**>) :: f (a :-> b) -> f a -> f b 

newtype (:->) a b x = HFunc (a x -> b x) 

infixr 5 :-> 

우리는 종류 * -> *와 기능을하기 위해서 :-> 래퍼 형식이 필요하지만, 우리가 <$>과 때와 수처럼이 잘 체인 기능을 응용 프로그램 우리를 허용하지 않습니다 일반 신청자는 <*>입니다. 나는 도우미와 같이 관리 할 수있다.

liftHA2 :: HApplicative f => (forall x. a x -> b x -> c x) -> f a -> f b -> f c 
liftHA2 f fa fb = hpure (fun2 f) <**> fa <**> fb where 
    fun2 = HFunc . (HFunc .) 

그러나 어떤 방법으로도 기능을 "리프트"하는 것이 좋을 것이다. 위의 인스턴스를 사용할 수있는 방법을

몇 가지 간단한 예제 :

data Example f = Example (f Int) (f String) 

instance HFunctor Example where 
    hfmap f (Example i s) = Example (f i) (f s) 

instance HApplicative Example where 
    hpure a = Example a a 
    Example (HFunc fi) (HFunc fs) <**> Example i s = Example (fi i) (fs s) 

e :: Example [] 
e = Example [1,2,3] ["foo", "bar"] 

e' :: Example ((,) Int) 
e' = hfmap (length &&& head) e -- Example (3,1) (2, "foo") 

e'' :: Example [] 
e'' = liftHA2 (++) e e -- Example [1,2,3,1,2,3] ["foo", "bar", "foo", "bar"] 

그래서, 내 질문은 : 무엇이라고 위의 typeclasses는 그들은 이미 hackage에서 일부 라이브러리에 의해 제공됩니다? Google 검색을 통해 Functor2linear-maps이고 HFunctormulti-rec인데 정확히 어느 것이 필요하지 않습니다.

래퍼를 사용하지 않고 :-> 래퍼를 쓰거나 다른 방법으로 쉽게 기능을 들일 수있는 방법이 있습니까?

답변

2

내가 생각하는 경향이있는 HFunctor는 (* -> *) -> * -> *입니다. 즉 Functor에 대한 합법적 인 Functor입니다. 이것은 당신이 생각하고있는 것과는 다른 특성을 가지고 있습니다.

응용 프로그램의 "monoidal"버전뿐만 아니라이를 정의하는 방법도 있습니다.

type Nat f g = forall a. f a -> g a 

class HFunctor (f :: (* -> *) -> * -> *) where 
    hfmap :: (Nat g h) -> Nat (f g) (f h) 

data Prod f g a = Prod (f a) (g a) 

class HFunctor f => HApplicative f where 
    hpure :: Nat g (f g) 
    htensor :: Nat (Prod (f g) (f h)) (f (Prod g h)) 

이 내용과 사용 방법에 대한 몇 가지 아이디어로 나중에 업데이트하려고합니다.

이것은 정확하게 당신이 요구하는 바가 아니지만, 나는 깨닫습니다. 그러나 나는 당신의 게시물로 그것을 시도해 보도록 영감을 받았습니다.

특정 유스 케이스에도 관심이 있습니다.

귀하의 두 가지 질문 A) 당신이 묘사 한 HFunctor는 이전에 여러 가지 상황에서 묘사되어 왔는데, 나는 기븐 스 (Gibbons)가 특별히 생각했으나 포장되어 있는지 모릅니다. 전에 확실히 Applicative를 보지 못했습니다. B) 유형 동의어를 부분적으로 적용 할 수 없기 때문에 래퍼가 붙어 있다고 생각합니다.

+0

차이점은 엔도 펑터 (endo-functor)를 정의하는 반면, OP는 객체가 일종의 '* -> *'(Hask에서 endo 펑터의 카테고리 여야 함)를 가진 일부 카테고리의 펑터를 Hask에게 정의하는 것입니다. –

+0

오른쪽 - "내가 생각한 것과는 다른 특성을 가지고있다"고 언급했듯이. – sclv

+0

작은 기술 주석 : 'f :: (* -> *) -> * -> *'는'func '가'HFunctor'일지라도 "functor의 functor" '모든 타입 생성자를 나타 내기 만하면된다.예를 들어, OP의'a : -> b는'a'와'b'가 ('a'가 반 행위 펑터가되기를 원한다면) 일반적으로 펑터가 아닙니다. 나는 이것을 기억하기 전에 몇 가지 잘못된 것들을 거의 썼다 ... –