21

我遇到了这样一种情况,我的代码可以从使用FunctorApplicative类似的抽象中受益,但是对于 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-mapsHFunctorin ,multi-rec但也不是我需要的。

另外,是否有某种方法可以在HApplicative没有:->包装器的情况下进行编写,或者是否有其他方法可以使功能提升更容易?

4

1 回答 1

2

我倾向于想到的 HFunctor 是(* -> *) -> * -> *——即函子上的合法函子。这与您所想的具有不同的特征。

以下是如何定义它,以及它上面的应用程序的“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)我认为你被包装器困住了,因为我们不能部分应用类型同义词。

于 2013-08-07T01:42:39.247 回答