我正在学习一些Haskell,我无法理解一些东西。我有这样的表达:Haskell表达式类型?
flip foldr id
而我需要找到它的类型。经过漫长的时间来解决这个问题,我放弃了,抬头一看正确的答案,那就是:
(a -> (a1 -> a1) -> a1 -> a1) -> [a] -> a1 -> a1
但我不明白为什么,我想! 我想[a] -> a1 -> a1
来自foldr
表达式,但我不知道如何继续。 谢谢,对不起我的英文!
我正在学习一些Haskell,我无法理解一些东西。我有这样的表达:Haskell表达式类型?
flip foldr id
而我需要找到它的类型。经过漫长的时间来解决这个问题,我放弃了,抬头一看正确的答案,那就是:
(a -> (a1 -> a1) -> a1 -> a1) -> [a] -> a1 -> a1
但我不明白为什么,我想! 我想[a] -> a1 -> a1
来自foldr
表达式,但我不知道如何继续。 谢谢,对不起我的英文!
检查类型所涉及的各个功能:
λ :t id
id :: a -> a
λ :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
λ :t flip
flip :: (a -> b -> c) -> b -> a -> c
然后尝试应用功能彼此怎么看的类型,将匹配的思考。
为避免名称冲突,我们可以将flip
的类型改写为(a1 -> b1 -> c1) -> b1 -> a1 -> c1
。
发生的第一件事是将flip
应用于foldr
。查看flip
和foldr
的类型,我们看到flip
类型中的a1 -> b1 -> c1
类型与foldr
类型得到“匹配”。这意味着a1
与a -> b -> b
匹配,b1
与b
匹配,而c1
与[a] -> b
匹配。
因此,在这样的背景下,flip
的类型变得((a -> b -> b) -> b -> [a] -> b) -> b -> (a -> b -> b) -> [a] -> b
(我刚刚更换每个a1
与a -> b -> c
,每个b1
与b
,每个c1
与[a] -> b
),以及flip foldr
类型是与第一同样的事情带走参数:b -> (a -> b -> b) -> [a] -> b
。
我们可以用ghci中迄今检查我们的工作:
λ :t flip foldr
flip foldr :: b -> (a -> b -> b) -> [a] -> b
现在我们采取这种类型的,它适用于id
类型(我们将写成a2 -> a2
)。这意味着b
与a2 -> a2
匹配,并且flip foldr
的类型变为(a2 -> a2) -> (a -> (a2 -> a2) -> (a2 -> a2)) -> [a] -> (a2 -> a2)
,flip foldr id
的类型与第一个参数带走的类型相同:(a -> (a2 -> a2) -> (a2 -> a2)) -> [a] -> a2 -> a2
。如果我们将a2
重写为a1
并删除一些括号,则这与您得到的答案相同。
我不明白应用哪个函数。 – DemianArdus
在'flip foldr id'中,'foldr'和'id'作为第一个和第二个参数传递给'flip',或者'id'作为参数传递给'flip foldr'的结果。 – Cirdec
@DemianArdus函数应用程序是左关联的,所以这意味着''flip foldr id'与'(flip foldr)id'相同。由于函数应用程序在haskell中的工作方式,这就像'foldr'和'id'都被传递给'flip'。 – Alec