我遇到了这样一种情况,我的代码可以从使用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 中的某个库提供?通过谷歌搜索,我想出了Functor2
inlinear-maps
和HFunctor
in ,multi-rec
但也不是我需要的。
另外,是否有某种方法可以在HApplicative
没有:->
包装器的情况下进行编写,或者是否有其他方法可以使功能提升更容易?