我有这段代码:
palindrome :: String -> Bool
palindrome x = x == reverse x
有没有办法以无点的方式重写它?
答案 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)
。