η减少可能吗?

st4*_*hoo 6 haskell pointfree

在下面的情况下是否可以应用eta减少?

let normalise = filter (\x -> Data.Char.isLetter x || Data.Char.isSpace x )
Run Code Online (Sandbox Code Playgroud)

我期待这样的事情是可能的:

let normalise = filter (Data.Char.isLetter || Data.Char.isSpace)
Run Code Online (Sandbox Code Playgroud)

......但事实并非如此

Ben*_*esh 10

您的解决方案不起作用,因为它(||)适用于Bool值,Data.Char.isLetter并且Data.Char.isSpace属于类型Char -> Bool.

pl给你:

$ pl "f x = a x || b x"
f = liftM2 (||) a b
Run Code Online (Sandbox Code Playgroud)

说明:liftM2提升(||)(->) rmonad,所以它的新类型是(r -> Bool) -> (r -> Bool) -> (r -> Bool).

所以在你的情况下我们会得到:

import Control.Monad
let normalise = filter (liftM2 (||) Data.Char.isLetter Data.Char.isSpace)
Run Code Online (Sandbox Code Playgroud)

  • 一个很好的补充([来自@JAbrahamson](http://stackoverflow.com/questions/21026021/intrigued-by-as-instances-of-monad-and-functor/21026411#comment31608950_21026411))是定义` (<||>)= liftM2(||)`,然后你可以将它用作`filter(isLetter <||> isSpace)`,甚至可以继续将它们组合成`filter(isLetter <||> isSpace <| |>(=='1'))`.我发现这种风格特别容易使用和吸引人. (10认同)

chi*_*chi 7

import Control.Applicative
let normalise = filter ((||) <$> Data.Char.isLetter <*> Data.Char.isSpace)
Run Code Online (Sandbox Code Playgroud)


Dan*_*zer 5

值得一看的另一个解决方案是箭头!

import Control.Arrow

normalize = filter $ uncurry (||) . (isLetter &&& isSpace)
Run Code Online (Sandbox Code Playgroud)

&&&采用两个函数(实际上是箭头)并将它们的结果拉到一个元组中.然后,我们只是不加考虑,||所以现在是时候了(Bool, Bool) -> Bool,我们都完成了!