如果foldr
的类型是
> :t foldr
forall a b. (a -> b -> b) -> b -> [a] -> b
和
> :t id
forall a. a -> a
然后我希望foldr (.) id
与foldr
具有相同的类型,而不是
> :t foldr (.) id
forall b. [b -> b] -> b -> b
看来我错误地认为合成是如何运作的,因为我认为对于f
f . id
会给f(id(x)) == f(x)
的函数f
,保留foldr (.) id
的类型。我误解的是什么会更加笼统地阐明{{1}}和作文的含义?
答案 0 :(得分:11)
这是{em>不与id
的合成,因为你来自foldr . id
(注意没有parens)。这确实只相当于foldr
,也许是类别理论中最重要的等价物,因此也是Haskell的基础。
相反,您在那里所做的是,将(.)
和id
作为参数传递给foldr
:放置.
在parens使它只是另一个表达式,所以普通的Haskell函数解析适用,即贪婪地使用连续的术语作为第一个的参数。你很幸运,这使得一个好的类型,例如succ (.) id
会给出荒谬的签名Enum ((c -> c) -> (a -> c) -> a -> c) => (a -> c) -> a -> c
。
通过编写
可以看出它与foldr
的完全一致
(.) :: (y->z) -> (x->y) -> (x->z)
统一(x->y) = (x->z)
与foldr
的论据一样,即y = z
,
(.) :: (y->y) -> (x->y) -> (x->y)
foldr (.) :: (x->y) -> [y->y] -> (x->y)
然后id
还需要x = y
,
foldr (.) id :: [x->x] -> (x->x)
答案 1 :(得分:6)
您没有使用foldr
撰写id
。那将是foldr . id
。您实际执行的操作是将 foldr
应用于(.)
,然后将此类应用的结果应用于id
。
答案 2 :(得分:1)
你在这里说的是你将要编写一个所有类型相同的函数列表(因为它们在列表中)。 id
是您要折叠的初始功能。完成所有这些操作后,您将获得一个功能。可能更容易将结果类型视为[b -> b] -> (b -> b)
。
顺便说一下,当您在Haskell中使用运算符并且想要中继它时,省略了parantheses。只有当你将它作为任何其他功能使用时才包括parantheses。