Недавно я сталкивался с ситуациями, когда мне нужно передать предикатную функцию в другую функцию, и довольно часто логика, которую я ищу, по существу "соответствует ли это значение этому шаблону?"
Похоже, что сопоставление с образцом предпочтительнее в объявлениях, do
блоках и списках, но есть ряд функций, которые принимают предикат a -> Bool
, где было бы очень удобно как-то передать шаблон. Так , например, takeWhile
, until
, find
, span
и т.д.
До сих пор я делал \a -> case a of MyCons _ -> True; otherwise -> False
или писал именованную функцию а-ля, 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
предложение, чтобы оно не загромождало основное определение. Конечно, если вам понадобится эта утилита более одного раза, вы определите ее как функцию верхнего уровня.