尝试了解Haskell如何评估pp1 [1,2,3,4]
以获取[(1,2),(2,3),(3,4)]
:
1. xnull f [] = []
2. xnull f xs = f xs
3. (/:/) f g x = (f x) (g x)
4. pp1 = zip /:/ xnull tail
我是这样开始的:
a) pp1 [1,2,3,4] = (zip /:/ xnull tail) [1,2,3,4] -- (rule 4).
b) (zip /:/ xnull tail) [1,2,3,4]
= (zip (xnull [1,2,3,4]) (tail) [1,2,3,4]) -- (rule 3)
c) -- I'm not sure how to continue because xnull receives a function
-- and a param, and in this case it only receives a param.
任何帮助?
答案 0 :(得分:4)
这是错误的
b) (zip /:/ xnull tail) [1,2,3,4] = (zip (xnull [1,2,3,4]) (tail) [1,2,3,4]) (rule 3)
因为它应该是
b) (zip /:/ xnull tail) [1,2,3,4] = (zip [1,2,3,4] (xnull tail [1,2,3,4])) (rule 3)
错误在于在zip /:/ xnull tail
而不是(zip /:/ xnull) tail
中阅读zip /:/ (xnull tail)
。
答案 1 :(得分:4)
继续扩展:
pp1 [1, 2, 3, 4] = zip /:/ xnull tail $ [1, 2, 3, 4]
-- inline (/:/) f g x = f x (g x)
-- f = zip, g = xnull tail, x = [1, 2, 3, 4]
-- therefore:
= zip [1, 2, 3, 4] (xnull tail $ [1, 2, 3, 4])
-- inline the definition of xnull and note that the argument is not null
-- so we just want f x, or tail [1, 2, 3, 4]
= zip [1, 2, 3, 4] (tail [1, 2, 3, 4])
-- evaluate tail
= zip [1, 2, 3, 4] [2, 3, 4]
-- evaluate zip
= [(1, 2), (2, 3), (3, 4)]
运营商总裁很重要。您没有指定(/:/)
的关联性,因此它默认为相对较弱。因此,(xnull tail)
比(/:/)
更紧密。
此外,作为附注,(/:/)
已作为(<*>)
Control.Applicative
存在于标准库中。它足够通用,因此可能很难看到,但Applicative
的{{1}}实例(或者更好地理解为函数Reader
)提供了这个确切的实例。它也被称为来自Applicative
的{{1}}。
ap
答案 2 :(得分:0)
我知道这有点老了。但无论如何,这是我的看法..
有助于查看定义
pp1 = zip /:/ xnull tail
= (zip) /:/ (xnull tail)
= (/:/) zip (xnull tail)
请注意(xnull tail)
周围的括号,表示函数应用程序具有更高的中缀运算符优先级。
现在(/:/)
的定义是返回另一个带有参数q
的函数x
并返回应用通过部分应用其第一个参数{{1}返回的函数的结果通过应用第二个参数r
返回的内容。
那是s
需要能够至少获得2个参数,而f
只需要至少1个。
g
请注意,(/:/) f g = q
where
q x = r s
where
r = f x
s = g x
为r
,因此f x
为q x
。
编写
会更清楚f x s
现在给出
f /:/ g = (\x -> f x (g x))
我们可以扩展到
pp1 = zip /:/ xnull tail
或
pp1 = q
where
q x = r s
where
r = zip x
s = xnull tail x
其余的只是用pp1 = (\x -> zip x $ xnull tail x)
替换x
并进行评估。