2012-02-03 80 views
2

我目前正在学习Haskell。我试图编写一个函数,如果其中一个是另一个的排列,则给出两个n个不同元素的列表返回true。我正在做这个练习。简单的Haskell编译错误不明白

我第一次写它:

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

你的第一个函数不测试一个列表是否是另一个列表的排列;它测试'v'中的所有元素是否都在'u'中,而不管'u'是否包含不在'v'中的元素,或者'v'是否包含比'u'更多的给定值的实例。 – jwodder 2012-02-03 20:32:49

+1

请注意,检查一个列表是否是另一个列表的一个更简单更有效的方法是对它们进行排序并检查结果是否相等。 (尽管这需要'Ord',而不仅仅是'Eq')。 – hammar 2012-02-03 20:34:20

+1

jwodder:是的,我知道,但是这两个列表具有相同的长度,并且由不同的元素组成,所以它归结为相同的东西。 Hammar:确实,这样更聪明。谢谢。 – user1188374 2012-02-03 20:41:07

回答

7

折叠必须采取的功能两个的论点。由于(&& whatever)\ x -> x && whatever相同,所以您给出了一个的论点的功能。

要在这里不使用lambda,需要一些方法来编写&&,一个双参数函数,(`elem` u),一个参数函数。 (请注意,(`elem` u)(flip elem) u\ x -> elem x u相同。)

+1

'pointfree'表示折叠函数应该写成'(。flip elem u)。 (&&)' – 2012-02-03 20:29:58

+0

@KevinBallard:是的。我打算留下实际的答案,让OP自己想出来。 – 2012-02-03 20:33:33

+2

不够公平,但如果你不熟悉奇怪的技巧(比如使用“。”部分),这种无意义表达式可能非常难以解决。当我必须这样做时,我通常会问'pointfree',然后决定结果是否容易理解,如果不是,我就避免使用它。当试图用'ap'和'= <<'记住' - >'monad技巧时(特别是记住哪一个将参数放在哪个顺序中),这会特别有用。 – 2012-02-03 20:35:39

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) . (&&)