내 코드가 Functor
및 Applicative
과 같은 추상화를 사용하지만 이점 유형이 (* -> *) -> *
인 경우에 도움이되는 상황이 발생했습니다. 더 높은 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 검색을 통해 Functor2
은 linear-maps
이고 HFunctor
은 multi-rec
인데 정확히 어느 것이 필요하지 않습니다.
래퍼를 사용하지 않고 :->
래퍼를 쓰거나 다른 방법으로 쉽게 기능을 들일 수있는 방법이 있습니까?
차이점은 엔도 펑터 (endo-functor)를 정의하는 반면, OP는 객체가 일종의 '* -> *'(Hask에서 endo 펑터의 카테고리 여야 함)를 가진 일부 카테고리의 펑터를 Hask에게 정의하는 것입니다. –
오른쪽 - "내가 생각한 것과는 다른 특성을 가지고있다"고 언급했듯이. – sclv
작은 기술 주석 : 'f :: (* -> *) -> * -> *'는'func '가'HFunctor'일지라도 "functor의 functor" '모든 타입 생성자를 나타 내기 만하면된다.예를 들어, OP의'a : -> b는'a'와'b'가 ('a'가 반 행위 펑터가되기를 원한다면) 일반적으로 펑터가 아닙니다. 나는 이것을 기억하기 전에 몇 가지 잘못된 것들을 거의 썼다 ... –