我如何以无点样式重写这个回文验证器?

时间:2013-10-13 19:39:29

标签: haskell pointfree

我有这段代码:

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

有没有办法以无点的方式重写它?

5 个答案:

答案 0 :(得分:8)

是的,因为任何函数都可以用无点样式编写。这里,(->) r(又名读者)的Applicative实例为您执行此操作,因为

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

您可能会认为这是来自SKI calculus的S-combinator(顺便说一下,return是K)。

您的Palindrome检查程序写为

x == reverse x

以中缀形式读取

(==) x (reverse x)

与上面的<*>定义相比,这导致了表达式

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

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

isPalindrome = (==) <*> reverse

可能不如原始表达式可读,因此不应使用。无点样式是为了便于阅读,仅在certian情况下有用。

答案 1 :(得分:2)

你可能认为这种方法是作弊的:

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

当然,大卫和弗雷尔也提出了适用的风格:

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)

答案 2 :(得分:2)

(->) r也是Monad,所以你的回文检查可以用monadic bind编写,这可能比上面的Applicative解决方案更具可读性

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

(&&&)Control.Arrow中定义,以便(f &&& g) x = (f x, g x)