逆向提升应用函子

时间:2016-07-21 10:41:58

标签: haskell applicative

我很确定这有一个简单的解决方案,但它使我无法找到一个直接的答案。

通常情况下,在应用liftA2时假设二元函数已被提升一次,签名如下所示:

liftA2'   :: (Applicative f1, Applicative f) 
             => (f a -> f b -> f c) -> f1 (f a) -> f1 (f b) -> f1 (f c)

是否可以应用“反向”,例如liftA2,例如:

inverseA2 :: (Applicative f, Applicative f1) 
             => (f a -> f b -> f c) -> f (f1 a) -> f (f1 b) -> f (f1 c)

作为一个具体的例子,我想获得这个功能:

f :: ([a] -> [b] -> [c]) -> [Maybe a] -> [Maybe b] -> [Maybe c]

一种方法是使用“打包”每个参数[Maybe a] -> Maybe [a]并“解包”Maybe [a] -> [Maybe a]应用普通liftA2的结果。我想避免这种情况,因为正如你所能想象的那样,打包具有破坏性(例如pack [Just 1, Nothing, Just 2] == Nothing)。

更新,正如@ user2407038所指出的那样,为了让f应用给定的函数,你需要一个与{em>一样的[Maybe a] -> [a]行的函数丢失信息。因此,对于这两个特定的仿函数,没有明显的方法来满足所提出的额外要求。但对于任何其他具有可逆函数f的两个仿函数f1forall a . f a -> f1 a,接受的答案完全可以作为此问题的解决方案。

1 个答案:

答案 0 :(得分:1)

我相信你可能已经想到了这一点,但我认为你不能用你所拥有的限制来做到这一点。如果你对你的约束更加自由,你会得到一些东西......

inverseA2 :: (Applicative f, Traversable f, Applicative f1, Traversable f1)
               => (f a -> f b -> f c) -> f (f1 a) -> f (f1 b) -> f (f1 c)
inverseA2 f x y = sequenceA (liftA2 f (sequenceA x) (sequenceA y))

我提出这个问题的唯一原因是,对于Maybe[]的特定示例,这些约束 都已满足,因此这样做是可行的那种情况。但仍然没有解决。

您还可以尝试为Data.Distributive编写自己的实例,为您提供distribute,类似于sequenceA ......

编辑包含@ dfeuer的建议。