我最近正在学习Haskell,而且我正在读“学习你是一个Haskell的Functors”,我才知道
((->)r)
也是一种Functors。(.)
相当于fmap
所以根据我的理解,fmap有两个参数。首先是要应用的函数,第二个是函子。
但是,我对这个表达式(.) (.) (.)
感到困惑。这是两种组合的组合,类型为(b -> c) -> (a1 -> a2 -> b) -> (a1 -> a2 -> c)
所以这是我的疑问。第一个(.)
有两个参数,第一个是组合函数本身。第二个参数也是组合函数。而组合函数本身并不是算子。那么这是一个有效的表达方式呢?
我确信我在这里遗漏了一些东西。有人可以填补空白并帮助我了解表达方式是否正确吗?
答案 0 :(得分:7)
忽略Functor
的{{1}}个实例;这是无关紧要的。这里只有两个问题:((->) r)
的类型,即
(.)
,以及函数应用程序左关联的事实。后者意味着(.) :: (b -> c) -> (a -> b) -> a -> c
与(.) (.) (.)
相同。
让我们首先尝试找到((.) (.)) (.)
的类型(最左边的那些,如果你愿意的话)。让我们将第一个(.) (.)
的类型写为(.)
,将第二个类型写为(b1 -> c1) -> (a1 -> b1) -> a1 -> c1
。我们将第一个应用于第二个,这使我们(b2 -> c2) -> (a2 -> b2) -> a2 -> c2
为b1
而(b2 -> c2)
为c1
。因此我们有
(a2 -> b2) -> a2 -> c2
可以简化为
(.) (.) :: (a1 -> (b2 -> c2)) -> a1 -> ((a2 -> b2) -> a2 -> c2)
现在让我们将其应用到最后一个(.) (.) :: (a1 -> b2 -> c2) -> a1 -> (a2 -> b2) -> a2 -> c2
(最右边的一个,如果你愿意的话)。如果它有签名(.)
,那么我们会看到(b3 -> c3) -> (a3 -> b3) -> a3 -> c3
必须是a1
,(b3 -> c3)
必须是b2
且(a3 -> b3)
必须是{{1} }}。因此,
c2
与
相同a3 -> c3
如果您进行重命名,这与您在问题中的内容相同。