Нещодавно я стикався з ситуаціями, коли мені потрібно передати предикатну функцію в іншу функцію, і досить часто логіка, яку я шукаю, по суті "чи відповідає це значення цій схемі?"
Здається, що відповідність шаблонів вважається кращою у do
розуміннях декларацій, блоків та списків, але є ряд функцій, які беруть предикат a -> Bool
, де було б дуже зручно якось передавати шаблон. Так , наприклад, takeWhile
, until
, find
, span
і т.д.
Поки що я робив \a -> case a of MyCons _ -> True; otherwise -> False
або писав названу функцію a la, let myPred (MyCons _) = True; myPred _ = False in
але вони обидва здаються жахливими і не дуже ідіоматичними. "Очевидний" (і неправильний) спосіб був би чимось подібним, \(MyCons _) -> True
але це спричиняє помилку за те, що він є частковим, природно, і навіть тоді відчувається, що має бути більш чистий спосіб.
Чи є більш складний / чистий спосіб зробити подібні речі? Або я йду про речі зовсім не так?
let myPred...
стиль поганий , але він відчуває себе набагато більш багатослівним, ніж я б очікував за дуже просту ідею, яка змушує мене замислитися, чи я гавкаю неправильне дерево.
maybe :: b -> (a -> b) -> Maybe a -> b
а bool :: a -> a -> Bool -> a
потім використовувати його з функціями, що виробляють бул, як аргументи (аргументи). наприклад myCons z f (MyCons x) = f x ; myCons z f _ = z
, тоді зателефонуйте myCons False (const True) aMyConsValue
. це майже те, що ви написали, просто є ще один рівень "непрямості" / "абстракції" за допомогою функціональних аргументів, вкладених у нього.
let
пунктом, який вам не подобається, - хоча я вважаю за краще рівнозначнеwhere
застереження, тому це не загрожує основним визначенням. Звичайно, якщо вам потрібна ця утиліта не раз, ви визначите її як функцію верхнього рівня.