0

我试图手动评估,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

谢谢,
塞巴斯蒂安。

4

2 回答 2

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) : [].

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

于 2014-04-25T21:33:34.037 回答
1

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

像这样的表达式func arg1 arg2 arg3可能看起来像一个应用于 3 个参数的函数,但实际上((func arg1) arg2) arg3),它func arg1会产生一个新函数,该函数被应用于arg2获得第三个函数,该函数最终应用于arg3.

like 定义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]的辅助定义。如果我们愿意,我们可以替换它,但我会让这个名字作为一个替身。替换回来(记住我们已经定义了):opeletopeope

(foldr1 操作 [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同样,我们可以在前面替换它,但这只是意味着复制我们ope上面写的任何地方的定义)。记住这ope实际上是单个参数的函数,即使我们被允许定义它看起来像它有两个参数一样方便,让我们一次应用一个参数:

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

所以我们现在有:

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

应用 lambda 给我们:

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

最后我们发现是组合 "pipeline" 的一个参数。我将在此停止,但您可以使用 的定义来进一步扩展它并找出传递给的最终函数。3f1 . (\x -> 2) . f2.3

因此,原始表达式中的 3 个值[f1, f2](\x -> 2)3不需要直接匹配为 定义的参数fc,因为它们根本不是它的所有参数。[f1, f2]是 的参数fc,(\x -> 2)是一个由 简单计算的参数fc [f1, f2](因此,如果需要,您可以将其视为“第二个参数” fc;重写等式很容易fc,使其直接显示为参数) . 3另一方面,它不是函数的参数,它接近于直接写在源代码中,它最终被传递给由表达式计算fc [f1, f2] (\x -> 2)的函数。

于 2014-04-26T05:03:10.913 回答