2013-10-13 13 views
5

我有这样的代码片段:我将如何以无点式重写此回文校验器?

palindrome :: String -> Bool 
palindrome x = x == reverse x 

有没有办法在一个自由的点式的改写呢?

+1

http://hackage.haskell.org/package/pointfree应用型溶液更具有可读性被写入 – 2013-10-13 19:51:07

回答

1

是的。

palindrome :: String -> Bool 
palindrome = ap (==) reverse 
8

是的,因为任何函数都可以用无点式书写。这里,(->) r应用型实例(又名阅读器)可以实现这个要求,因为

(f <*> g) x = f x (g x) 

您可能认识到这一点从SKI calculus的S-组合子(return为K的方式)。

你的回文检查被写为

x == reverse x 

其中在缀形式读取

(==) x (reverse x) 

,并通过与<*>定义上述该比较导致表达

isPalindrome x = ((==) <*> reverse) x 

其中您可以删除尾部x以获得解决方案

isPalindrome = (==) <*> reverse 

这可能比原始表达式更不可读,因此不应使用该原因。无点式是为了可读性,并且仅在特殊情况下才有用。

+5

“这可能比原始表达更不可读,因此不应该使用”是一个有趣的说法。有Pythonistas会争辩说'map'总是比列表理解更不可读。什么是可读的真的取决于什么成语流行。一个曾经看到应用风格的人可能会将无点的版本理解为“平等而非逆转”或其他,这很容易理解。而流行的成语是随着时间而变化的,所以如果你想让它在特定的方向上改变,你可以节省地使用“怪异”的语言。 – kqr

+1

@kqr右侧,有人用于应用程序( - >)使用此代码没有问题。但是请注意,当您第一次了解它时,基本应用程序( - >)的含义非常高。这里的代码非常简单,但是可以通过只读中介程序员的方式来进行编写。 – David

+0

@大卫的权利,但'<*>'和'加入'应该是[一个基本的点免费风格曲目](http://stackoverflow.com/a/11050971/849891)的一部分,可以为自己学习(除了是一个应用实例)。 –

2

你可能会认为这种方法欺骗:

palindrome :: Eq a => [a] -> Bool 
palindrome = palindrome' 
    where palindrome' xs = xs == reverse xs 

当然另外还有一个应用性的风格,大卫和freyrs建议:

palindrome'' :: Eq a => [a] -> Bool 
palindrome'' = (==) <*> reverse 

但如何对这种表达的折?

palindrome''' :: Eq a => [a] -> Bool 
palindrome''' = (foldl (\b (x, y) -> b && x == y) True) 
       . (uncurry zip) 
       . reverse' 
    where reverse' xs = (xs, reverse xs) 
+1

尽管'reverse'不是无点的,所以你可以说这和你的第一个一样。为了使'反向'免费,你会再次需要应用版本,使它与第二个例子的排序相同! ('foldl' lambda也不是无点的,但是我有一种感觉,那就是'Data.List'中'all'的重新实现,这样表达式就可以快速地变成无点状态。) – kqr

+0

fold with'( &&)'只是'和':'回文=和。 uncurry(zipWith(==))。加入((,)。reverse)'。但当然'和。 uncurry(zipWith(==))'只是'uncurry(==)'的一个实现,因为[swish的答案](http://stackoverflow.com/a/19350803/849891)就是例证。 :) –

1
palindrome :: String -> Bool 
palindrome = uncurry (==) . (id &&& reverse) 

(&&&)Control.Arrow使得(f &&& g) x = (f x, g x)定义。

2

(->) r也是单子,所以你的回文检查可以与一元结合,这可能是比上面

palindrome :: String -> Bool 
palindrome = reverse >>= (==) 
+0

一个侧面说明:'k k == g >> =(flip k)== k <*> g == \ x - > k x(x r)'。所以你的代码表达了'reverse xs == xs'。 –