我正在学习Haskell。我正在尝试编写一个函数,给定两个n个不同元素的列表,如果一个是另一个的排列,则返回true。我这样做是为了练习。
我首先把它写成:
isPermut :: (Eq a)=>[a]->[a]->Bool
isPermut u v = foldl (\acc x -> acc && (elem x u)) True v
这似乎有效。我现在尝试在没有lambda表达式的情况下重写它。所以我试试:
isPermut :: (Eq a)=>[a]->[a]->Bool
isPermut u v = foldl (&& (flip $ elem u)) True v
这给了我一个编译错误:
Couldn't match expected type `b0 -> Bool' with actual type `Bool'
Expected type: Bool -> b0 -> Bool
Actual type: Bool -> Bool
In the first argument of `foldl', namely `(&& (flip $ elem u))'
In the expression: foldl (&& (flip $ elem u)) True v
这个错误是什么意思?在没有lambda的情况下编写函数的正确方法是什么? 感谢。
答案 0 :(得分:7)
Folds必须使用两个参数的函数。您提供了一个参数的函数,因为(&& whatever)
与\ x -> x && whatever
相同。
为了不在这里使用lambda,你需要一些方法来构造&&
,一个双参数函数,(`elem` u)
,一个参数函数。 (请注意,(`elem` u)
与(flip elem) u
或\ x -> elem x u
相同。)
答案 1 :(得分:7)
让我们一步一步。
\acc x -> acc && (elem x u)
= { write (&&) in prefix form }
\acc x -> (&&) acc (elem x u)
= { definition of flip }
\acc x -> (&&) acc (flip elem u x)
= { definition of (.) }
\acc x -> ((&&) acc . flip elem u) x
= { eta reduction }
\acc -> (&&) acc . flip elem u
= { write (.) in prefix form }
\acc -> (.) ((&&) acc) (flip elem u)
= { definition of flip }
\acc -> flip (.) (flip elem u) ((&&) acc)
= { definition of (.) }
\acc -> (flip (.) (flip elem u) . (&&)) acc
= { eta reduction }
flip (.) (flip elem u) . (&&)
= { syntax sugar for sections }
(. flip elem u) . (&&)