Haskell如何评估使用部分应用程序定义的此函数?

时间:2014-04-25 17:39:02

标签: haskell partial-application equational-reasoning

尝试了解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.

任何帮助?

3 个答案:

答案 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 xq 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并进行评估。