功能评估结果

时间:2014-04-25 21:20:57

标签: haskell equational-reasoning

我试图手动评估fc [f1, f2] (\x -> 2) 3但我没有意识到如何匹配三个参数:[f1,f2],(\ x - > 2)和3与函数定义,任何帮助?

功能定义:

fc xss = \f -> let ope x y = x . f . y in foldr1 ope xss

f1, f2 :: Int -> Bool
f1 x = (x `mod` 3) == 0
f2 x = (x `mod` 5) == 0

谢谢,
安。

2 个答案:

答案 0 :(得分:4)

好吧,首先做一些η -expansion

fc :: [a->b] -> (b->a) -> a->b
fc xss f = let ope x y = x . f . y in \q -> foldr1 ope xss q
 fc xss f q = let ope x y = x . f . y in foldr1 ope xss q

然后可能内联let

 fc xss f q = foldr1 (\x y -> x . f . y) xss q

您可以将[f1, f2]写为(==0).(`mod`3) : (==0).(`mod`5) : []

现在它应该很容易,记住右折叠只是用折叠函数替换所有:

答案 1 :(得分:1)

请记住,Haskell中的所有函数都是单个结果的单个参数的函数。

func arg1 arg2 arg3这样的表达式可能看起来就像应用于3个参数的函数一样,但它真的是((func arg1) arg2) arg3),其中func arg1会产生新的函数,应用于arg2以获取第3个函数,该函数最终应用于arg3

func arg1 arg2 arg3 = ...这样的定义是等同定义的语法糖,例如func arg1 = \arg2 -> (\arg3 -> ... ),我们已经明确地写出了沿途产生的中间函数。

因此fc [f1, f2] (\x -> 2) 3正在将fc应用于[f1, f2],然后应用该结果。很清楚如何将fc应用于一个参数(因为它的定义只有一个参数),所以我们只需要做第一步,看看我们得到了什么。

fc [f1, f2] = \f -> let ope x y = x . f . y in foldr1 ope [f1, f2]

这给了我们一个lambda函数,这是可以应用的东西。将其替换为原始表达式可以得到:

(\f -> let ope x y = x . f . y in foldr1 ope [f1, f2]) (\x -> 2) 3

现在我们再次将一个函数(\f -> ...)应用于一个参数(\x -> 2)。结果再次应用(3),但我们稍后会担心。

(\f -> let ope x y = x . f . y in foldr1 ope [f1, f2]) (\x -> 2)
  = let ope x y = x . (\x -> 2) . y in foldr1 ope [f1, f2]

这样就给了我们foldr1 ope [f1, f2]的表达式,ope的辅助定义let;如果我们愿意,我们可以替换它,但我会让名字ope保持原样。将其替换回来(记住我们已定义ope):

(foldr1 ope [f1,f2])3

foldr等同于以下内容:

foldr1 f [x] = x
foldr1 f (x:xs) = f x (foldr1 f xs)

因此,我们可以扩展foldr1表达式,记住[f1, f2]只是另一种写作方式f1:[f2]

foldr1 ope (f1:[f2]) = ope f1 (foldr1 ope [f2])
                     = ope f1 f2

替换回来给我们:

ope f1 f2 3

现在让我们使用我们预留的ope的定义:ope x y = x . (\x -> 2) . y(同样,我们可以在之前替换它,但它只是意味着在我们编写的所有地方复制出定义{{1 }} 以上)。记住ope实际上是单个参数的函数,即使我们被允许定义它看起来像是为了方便它有两个参数,让我们一次应用一个参数: / p>

ope

所以我们现在有:

ope f1 = \y -> f1 . (\x -> 2) . y

应用lambda给我们:

(\y -> f1 . (\x -> 2) . y) f2 3

终于我们发现(f1 . (\x -> 2) . f2) 3 是作文的一个参数"管道" 3。我将在此停止,但您可以使用f1 . (\x -> 2) . f2的定义进一步扩展,并找出传递给最终函数.的内容。

因此,原始表达式中的3个值3[f1, f2](\x -> 2)不需要直接匹配为3定义的参数,因为他们根本不是所有的论据。 fc[f1, f2]的参数,fc是一个由(\x -> 2)简单计算的参数(因此您可以将其视为"第二个参数&#34 ;如果你愿意,可以fc [f1, f2];重写fc的等式非常容易,因此它可以直接作为参数出现。另一方面,fc不是一个函数的参数,它与源代码中直接写入的函数有关,它最终被传递给计算的函数表达式3