我和Chapter 8 from 一起疯了。
在8.3节中,Bartosz定义了这种类型
newtype BiComp bf fu gu a b = BiComp (bf (fu a) (gu b))在这里,如果我对Haskell有一点了解,bf、fu和gu是类型构造函数、类(* -> *) -> (* -> *) -> * -> * -> *的bf和gu (就像Maybe或[]),而a和d13是*的一般类型;=左侧的BiComp 是要写入的类型构造函数,而右边的BiComp 是值构造函数,所以它是(bf (fu a) (gu b)) -> BiComp bf fu gu a b类型的。
然后,作者将BiComp设为a和b中的双函子,条件是类型构造器参数bf也是Bifunctor,且类型构造函数fu和gu是Functor的:
instance (Bifunctor bf, Functor fu, Functor gu) => Bifunctor (BiComp bf fu gu) where
bimap f1 f2 (BiComp x) = BiComp ((bimap (fmap f1) (fmap f2)) x)到目前为止,这一切对我来说都是合理的。但是,对类型构造函数和值构造函数使用相同的名称可能会使我迷路。
现在我想提出以下几点意见:
定义右边的
bimap是利用这些约束的:假定bimap是在构造器bf的任何类型的Bifunctor实例中定义的,因此bimap具有(a -> a') -> (b -> b') -> bf a b -> bf a' b'类型;我认为这比下面的内容更不有趣,因为它毕竟只是Bifunctor类型class在8.1中的签名;相反,左边的(a -> a') -> (b -> b') -> BiComp bf fu gu a b -> BiComp bf fu gu a' b'.
bimap是我们定义的使BiComp在其第4和第5个参数中成为Bifunctor的函数;而参数f1和f2是必须作用于类型实体(即BiComp的第4和第5个参数)的函数;因此,bimap的类型是Bifunctor。这是正确的吗?
如果是这样的话,那么我就不明白以下几点
bimap :: (fu a -> fu a') -> (gu b -> gu b') -> bf (fu a) (gu b) -> bf (fu a') (gu b')因为这是右边bimap的类型,这是我在上面的要点中写的类型,只是它是用a = fu a、a' = fu a'等编写的。
我是不是漏掉了什么东西(或者想太多了.)?
发布于 2021-01-23 18:51:56
你们关系很好。
首先,您有错误的bf类型。它实际上只是* -> * -> *,考虑到它将是一个Bifunctor,这与预期完全相同。当然,这种BiComp是相当疯狂的:
BiComp :: (* -> * -> *) -> (* -> *) -> (* -> *) -> * -> * -> *从技术上讲,对于你的子弹点中的类型,它们都是正确的,但是使用新的类型变量可能会有帮助(尤其是对于你第一个子弹点中的类型!)让这一切变得更清楚。实际上,右边的bimap具有以下类型
bimap :: forall c c' d d'. (c -> c') -> (d -> d') -> bf c d -> bf c' d'我们需要使用它将输入值(类型为bf (fu a) (gu b) )转换为bf (fu a') (gu b')类型的输出值。我们只有让c ~ fu a, c' ~ fu a', d ~ gu b, d' ~ gu b'这样做,我们才能做到这一点。让我们看看这对RHS bimap的影响
bimap :: (fu a -> fu a') -> (gu b -> gu b') -> bf (fu a) (gu b) -> bf (fu a') (gu b')啊哈!这正是你在右手边发现的!而且,我们可以提供我们所需要的论据。首先是fu a -> fu a'类型的函数。我们有一个给定的函数f1 :: a -> a',我们知道fu是一个函子,所以我们可以用fmap f1得到我们需要的函数。f2和fmap f2也是如此,一切都很顺利。
https://stackoverflow.com/questions/65862981
复制相似问题