我遇到了这样一种情况,我的代码可以从使用Functor和Applicative类似的抽象中受益,但是对于 kind 类型(* -> *) -> *。可以RankNTypes像这样定义更高种类的函子
class HFunctor f where
hfmap :: (forall x. a x -> b x) -> f a -> f b
但更高版本的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 :->
我们需要:->wrapper 类型才能使用 kind 函数,* -> *但这并不能让我们像普通 Applicatives 那样很好地链接函数应用程序。我可以使用助手进行管理,例如<$><*>
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"]
所以,我的问题是:上面提到的类型类是什么,它们是否已经由 hackage 中的某个库提供?通过谷歌搜索,我想出了Functor2inlinear-maps和HFunctorin ,multi-rec但也不是我需要的。
另外,是否有某种方法可以在HApplicative没有:->包装器的情况下进行编写,或者是否有其他方法可以使功能提升更容易?