在列表上使用haskell中的flip和filter函数

在列表上使用haskell中的flip和filter函数,haskell,Haskell,一个哈斯凯尔新手,如果这是一个相当基本的问题,我道歉。我想写一个函数,它接受两个变量列表,然后返回第一个列表,并从第二个列表中删除所有变量。例如,我想要以下输出 *Main>filterVariables[“y”、“z”、“a1”、“a2”][“y”、“a1”、“a3”] [“z”,“a2”] 这就是我迄今为止所写的: type Var = String data Term = Variable Var | Lambda Var Term | Apply Term

一个哈斯凯尔新手,如果这是一个相当基本的问题,我道歉。我想写一个函数,它接受两个变量列表,然后返回第一个列表,并从第二个列表中删除所有变量。例如,我想要以下输出

*Main>filterVariables[“y”、“z”、“a1”、“a2”][“y”、“a1”、“a3”]

[“z”,“a2”]

这就是我迄今为止所写的:

type Var = String

data Term =
    Variable Var
  | Lambda   Var  Term
  | Apply    Term Term


variables :: [Var]
variables =  [l:[] | l <- ['a'..'z']] ++ [l:show x | x <- [1..], l <- ['a'..'z']]

--works but the wrong way around!!!
filterVariables :: [Var] -> [Var] -> [Var]
filterVariables lst = filter ( `notElem` lst)
我收到以下错误消息:

Couldn't match type ‘[Var]’ with ‘[Var] -> c0’
      Expected type: [Var] -> [Var] -> c0
        Actual type: [Var] -> [Var]
    • Possible cause: ‘filter’ is applied to too many arguments
      In the first argument of ‘flip’, namely ‘(filter (`notElem` lst))’
      In the expression: flip (filter (`notElem` lst))
      In an equation for ‘filterVariables’:
          filterVariables lst = flip (filter (`notElem` lst))

如何正确使用flip?或者你能推荐另一种方法吗?

我认为这样写可能更简单:

filterVariables :: Eq => [a] -> [a] -> [a]
filterVariables items lst = filter (`notElem` lst) items
你不能在
filter(`notElem`lst)
flip
,因为
filter(
notElem
lst)
有类型
[a]->[a]
flip
有类型
flip:(b->a->c)->a->b->c
。因此,这意味着
[a]->[a]
b->a->c
的类型相同,但这意味着
[a]
a->c
是相同的类型

但是,您可以通过实现无点变量来使用
flip

filterVariables :: (Foldable t, Eq a) => [a] -> t a -> [a]
filterVariables =flip (filter . flip notElem)
filterVariables::(可折叠的t,等式a)=>[a]->ta->[a]
filterVariables=flip(filter.flip notElem)

实际上,这里是
过滤器。flip notElem
具有类型
过滤器。flip notElem::(Eq a,Foldable t)=>ta->[a]->[a]
,因为它相当于
\xs->filter(flip notElem xs)ys
或更短的
\xs->filter(`notElem`xs)
,所以我们可以翻转
xs
ys
flip
函数采用两个输入的参数函数。因此,如果要将参数翻转到
filterVariables
,则必须以两个参数的形式将其转换为
flip
it。在您的版本中:

filterVariables lst = flip (filter ( `notElem` lst))
你已经接受了一个论点,只剩下一个可以接受。我们可以通过首先将
lst
参数移动到等式的另一侧来解决此问题:

filterVariables lst = filter ( `notElem` lst) -- original, accepts one more argument
filterVariables = \lst -> filter (`notElem` lst) -- now a function which accepts two arguments
filterVariables = flip (\lst -> filter (`notElem` lst)) -- flipped form

为什么不简单地编写
filterVariables items lst=filter(`notElem`lst)items
?还有一个库函数,
Data.List.(\\)
,您可以
将其翻转到心底。还有
l:[]
=
[l]
。您将把\\放在哪里?
filterVariables lst = filter ( `notElem` lst) -- original, accepts one more argument
filterVariables = \lst -> filter (`notElem` lst) -- now a function which accepts two arguments
filterVariables = flip (\lst -> filter (`notElem` lst)) -- flipped form