首页 > 解决方案 > Haskell中`join bimap`的签名

问题描述

在 codewars 的一个解决方案中,我遇到了以下表达式:

join bimap

哪里join :: Monad m => m (m a) -> m abimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d。结果表达式的类型为:Bifunctor p => (c -> d) -> p c c -> p d d

我可以猜想 的类型bimap可以写成 形式 (->) (a->b) ((->) (c->d) p a c -> p b d),但我不知道如何p a c转为p c c和。请给我一些提示如何解开这个难题。p b dp d d

标签: haskelltype-inferenceparametric-polymorphism

解决方案


首先,让我们看一下join应用于函数的类型。假设你有一个函数f :: t -> u -> v;或者,等价地,f :: (->) t ((->) u v)。我们可以尝试join :: Monad m => m (m a) -> m a通过比较两种类型来统一这一点:

           (->) t ((->) u v)
Monad m => m      (m      a) -> m a

因此,我们可以尝试通过设置m ~ (->) t和来统一类型a ~ v

(->) t ((->) u v)
(->) t ((->) t v) -> (->) t v

但是有一个问题:我们还需要t ~ u这些类型匹配!因此我们可以得出结论,join只有当前两个参数具有相同类型时才能应用于函数——如果它们不是,我们只能join在有办法使它们相等的情况下应用于该函数。

现在,想想bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d。通常,、 、ab可以是任何类型。但是如果你想应用于,这会增加前两个参数必须具有相同类型的约束:即。由此我们可以得出结论和。但是,当然,这意味着必须与 相同,并且与 相同,解决难题。cdpjoinbimapbimap(a -> b) ~ (c -> d)a ~ cb ~ dp a cp a ap b dp b b


推荐阅读