简体   繁体   English

类型的函数和应用程序(* - > *) - > *

[英]Functors and Applicatives for types of kind (* -> *) -> *

I ran into a situation where my code would benefit from using Functor and Applicative -like abstractions, but for types of kind (* -> *) -> * . 我遇到了一种情况,我的代码将从使用Functor和类似Applicative的抽象中受益,但对于类型(* -> *) -> * Defining a higher-kinded functor can be done with RankNTypes like this 定义更高级的仿函数可以使用这样的RankNTypes来完成

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

But the higher kind version of Applicative is a bit trickier. 但是更高版本的Applicative有点棘手。 This is the best I could come up with: 这是我能想到的最好的:

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 :->

We need the :-> wrapper type in order to have functions with the kind * -> * , but this doesn't let us nicely chain function application like we can with <$> and <*> for normal Applicatives. 我们需要:->包装器类型,以便具有类型* -> *函数,但这不能让我们很好地链接函数应用程序,就像我们可以使用<$><*>使用普通的Applicatives。 I can manage with helper such as 我可以用帮手来管理

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 .)

But it would be nice to have a general way to "lift" functions of any arity. 但是有一个通用的方法可以“解除”任何arity的功能。

Some simple examples how the above instances can be used: 一些简单的例子如何使用上述实例:

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"]

So, my question is: what are the above typeclasses called and are they already provided by some library in hackage? 所以,我的问题是:上面提到的类型类是什么,它们是否已经被一些库中的hackage提供了? By googling I came up with Functor2 in linear-maps and HFunctor in multi-rec but neither does exactly what I need. 谷歌搜索,我想出了Functor2linear-mapsHFunctormulti-rec但同样没有正是我需要的。

Also, is there some way to write HApplicative without the :-> wrapper or some other way to make function lifting easier? 另外,是否有一些方法可以编写HApplicative而不使用:->包装器或其他一些方法来使函数提升更容易?

The HFunctor I tend to think of is (* -> *) -> * -> * -- ie a legitimate functor on functors. 我倾向于认为的HFunctor是(* -> *) -> * -> * - 即仿函数上的合法函子。 This has different characteristics than the one you're thinking of. 这与你想到的不同。

Here's how to define it, as well as the "monoidal" version of an applicative on it. 以下是如何定义它,以及应用程序的“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))

I'll try to update later with some ideas about what this is and how to use it. 我稍后会尝试更新一些关于这是什么以及如何使用它的想法。

This isn't exactly what you're asking for, I realize, but I was inspired to try it out by your post. 我意识到,这并不是你所要求的,但我的灵感来自你的帖子。

I'd be interested in your specific use case as well. 我也对你的具体用例感兴趣。

To your two specific questions A) The HFunctor you describe has been described before on various occasions, I think by Gibbons in particular, but I don't know of it packaged up. 关于你的两个具体问题A)你所描述的HFunctor之前已经在不同场合进行了描述,我特别想到Gibbons,但我不知道它是否打包过。 I certainly haven't seen the Applicative before. 我当然没有见过申请人。 B) I think you're stuck with the wrapper because we can't partially apply type synonyms. B)我认为你坚持使用包装器,因为我们不能部分应用类型同义词。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM