Kar*_*her 1 haskell type-inference parametric-polymorphism
在 codewars 的解决方案之一中,我遇到了以下表达式:
join bimap
Run Code Online (Sandbox Code Playgroud)
其中join :: Monad m => m (m a) -> m a, 和 bimap :: 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 dto p d d。请给我一些如何解开这个谜题的提示。
join首先,让\xe2\x80\x99s 看看应用于函数的 as 类型。让\xe2\x80\x99s 说你有一个函数f :: t -> u -> v;或者,等效地,f :: (->) t ((->) u v). 我们可以尝试join :: Monad m => m (m a) -> m a通过比较这两种类型来统一这一点:
(->) t ((->) u v)\nMonad m => m (m a) -> m a\nRun Code Online (Sandbox Code Playgroud)\nm ~ (->) t因此,我们可以尝试通过设置和来统一类型a ~ v:
(->) t ((->) u v)\n(->) t ((->) t v) -> (->) t v\nRun Code Online (Sandbox Code Playgroud)\n但有一个问题:我们还需t ~ u要让这些类型匹配!因此我们可以得出结论,join只有当前两个参数具有相同类型 \xe2\x80\x94 时,才能应用于函数,如果不是,则只有在有join办法使它们相等的情况下,我们才能应用于该函数。
现在,想一想bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d。通常,a、b、c、d和p可以是任何类型。但如果您想应用于join,bimap这会增加一个约束,即 的前两个参数bimap必须具有相同的类型:即(a -> b) ~ (c -> d)。由此我们可以得出结论a ~ c和b ~ d。但是,当然,这意味着p a c必须与p a a和p b d相同p b b,才能解决难题。