2014-05-07 13 views
6

Aşağıdaki durumda eta azaltımı uygulamak mümkün mü?Eta azaltma mümkün mü?

let normalise = filter (\x -> Data.Char.isLetter x || Data.Char.isSpace x) 

Böyle bir şey mümkün olmasını bekliyordum:

let normalise = filter (Data.Char.isLetter || Data.Char.isSpace) 

... ama değil

Sen Any Monoid ve geri dönen fonksiyonlar için monoid örneğinin yararlanmak

cevap

10

Çözümünüz çalışmıyor, çünkü (||), Bool değerlerinde ve Data.Char.isLetter ve Data.Char.isSpace, Char -> Bool türünde çalışır.

pl verir:

$ pl "f x = a x || b x" 
f = liftM2 (||) a b 

Açıklama: yeni tip liftM2 asansörleri (->) r monad için (||), böylece (r -> Bool) -> (r -> Bool) -> (r -> Bool) olduğunu.

Yani sizin durumda biz alırsınız: bakarak

import Control.Monad 
let normalise = filter (liftM2 (||) Data.Char.isLetter Data.Char.isSpace) 
+10

Buna ek olarak (@JAbrahamson'dan çalınmış) (http://stackoverflow.com/questions/21026021/intrigued-by-as-instances-of-monad-and-functor/21026411#comment31608950_21026411)) '(<||>) = liftM2 (||) 'öğesini tanımlamak için,' filtre (isLetter <||> isSpace)' olarak kullanabilir ve hatta bu filtreleri birleştirmeye devam edebilirsiniz (isLetter <||> isSpace <||> (== '1')) '. Bu stili özellikle kullanımı ve çekici olması için kolay buluyorum. – bheklilr

2

monoz değerleri:

import Data.Monoid 
import Data.Char 

let normalise = filter (getAny . ((Any . isLetter) `mappend` (Any . isSpace))) 
7
import Control.Applicative 
let normalise = filter ((||) <$> Data.Char.isLetter <*> Data.Char.isSpace) 
5

Başka bir çözüm değerinde okları içerir!

import Control.Arrow 

normalize = filter $ uncurry (||) . (isLetter &&& isSpace) 

&&& iki işlevi (gerçekten oklar) alır ve bir demet halinde bir araya sonuçlarını fermuarlar. O zaman sadece || uncurry olur, bu yüzden (Bool, Bool) -> Bool olur ve hepimiz bitti!