在更高阶函数中简化匿名函数

时间:2013-12-20 07:01:53

标签: haskell higher-order-functions

假设我有以下类型:

data Test = Test1 | Test2
            deriving (Eq, Show)

data TestDS = TestDS {
      testField1 :: String,
      testField2 :: Test
    } deriving (Eq, Show)

testFilter :: [TestDS] -> [TestDS]
testFilter tdata = filter (\x -> testField2 x == Test2) tdata

是否可以将上述过滤器功能转换为以下形式:

filter (Test2 == testField2) tdata

(上面的过滤函数当然会产生编译错误)

3 个答案:

答案 0 :(得分:9)

这是你想要的吗?

filter ((Test2 ==) . testField2) tdata

请记住(Test2 ==)和testField2都是可以编写的函数。

答案 1 :(得分:7)

filter (\x -> testField2 x == Test2) tdata

看来你的括号错误地出现了。代码不是

filter ((\x -> testField2 x) == Test2) tdata

真的是

filter (\x -> (testField2 x == Test2)) tdata

因此,eta减少规则(“\x -> foo x可以替换为foo”)不适用。

要使其适用,您需要将x移动到lambda体的末尾。首先,我们使用==的交换性:

filter (\x -> (Test2  == (testField2 x))) tdata

我加上额外的括号来澄清eta-reduction仍然不适用。现在的想法是应用函数组合规则(“foo (bar x)可以替换为foo . bar”),但为了演示我们将使用的示例中的foobar ==的前缀形式:

filter (\x -> ((==) Test2 (testField2 x))) tdata

现在很明显foo(==) Test2bartextField2

filter ((==) Test2 . testField2)) tdata

现在我们可以使用所谓的运算符部分代替(==) Test2(== foo)(括号必须)与\x -> x == foo相同。 (foo ==)与'x -> foo == x相同。

filter ((== Test2) . testField2)) tdata

filter ((Test2 ==) . testField2)) tdata

答案 2 :(得分:0)

你可以说

filter ((Test2 ==) . testField2) tdata

或(我的偏好)使用列表理解:

[ t | t@TestDS{testField2 = Test1} <- tdata ]