假设我有以下类型:
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
(上面的过滤函数当然会产生编译错误)
答案 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
”),但为了演示我们将使用的示例中的foo
和bar
==
的前缀形式:
filter (\x -> ((==) Test2 (testField2 x))) tdata
现在很明显foo
为(==) Test2
而bar
为textField2
:
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 ]