Нещодавно я стикався з ситуаціями, коли мені потрібно передати предикатну функцію в іншу функцію, і досить часто логіка, яку я шукаю, по суті "чи відповідає це значення цій схемі?"
Здається, що відповідність шаблонів вважається кращою у 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застереження, тому це не загрожує основним визначенням. Звичайно, якщо вам потрібна ця утиліта не раз, ви визначите її як функцію верхнього рівня.