Возможно ли снижение эта?

Можно ли применить сокращение eta в приведенном ниже случае?

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

Я ожидал, что что-то вроде этого будет возможно:

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

...но это не так


person st4hoo    schedule 07.05.2014    source источник


Ответы (3)


Ваше решение не работает, потому что (||) работает с Bool значениями, а Data.Char.isLetter и Data.Char.isSpace относятся к типу Char -> Bool.

pl дает вам:

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

Объяснение: liftM2 поднимает (||) до монады (->) r, поэтому новый тип (r -> Bool) -> (r -> Bool) -> (r -> Bool).

Итак, в вашем случае мы получим:

import Control.Monad
let normalise = filter (liftM2 (||) Data.Char.isLetter Data.Char.isSpace)
person Benesh    schedule 07.05.2014
comment
Хорошее дополнение к этому (украдено у @JAbrahamson) заключается в определении (<||>) = liftM2 (||), тогда вы можете использовать его как filter (isLetter <||> isSpace) и даже продолжать комбинировать их, как filter (isLetter <||> isSpace <||> (== '1')). Я нахожу этот стиль особенно простым в использовании и привлекательным. - person bheklilr; 07.05.2014

Еще одно решение, на которое стоит обратить внимание, связано со стрелками!

import Control.Arrow

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

&&& берет две функции (на самом деле стрелки) и объединяет их результаты в один кортеж. Затем мы просто удаляем ||, так что время становится (Bool, Bool) -> Bool, и все готово!

person Daniel Gratzer    schedule 07.05.2014

Вы можете воспользоваться моноидом Any и экземпляром моноида для функций, возвращающих моноидные значения:

import Data.Monoid
import Data.Char

let normalise = filter (getAny . ((Any . isLetter) `mappend` (Any . isSpace)))
person Lee    schedule 07.05.2014