What to name functions that encapsulate destructuring and call callbacks?

I have a few functions in my 7GUIs implementation that are named map[Something] but which clearly do not map in the usual sense. The general idea behind all the functions is that they encapsulate the destructuring logic for a data structure and call callbacks when one of the patterns match. I would like to get your advice on renaming them appropriately.

Examples

I’ve definitely found this approach useful but naming is hard so your help will be greatly appreciated.

To me, those functions looks like case-of in disguise.

Instead of:

mapBooking :
    { onOneWay : Date -> a
    , onReturn : Date -> Date -> a
    , default : a
    }
    -> Booking
    -> a
mapBooking { onOneWay, onReturn, default } { flight, start, end } =
    case ( flight, start, end ) of
        ( OneWay, Valid startDate, _ ) ->
            onOneWay startDate

        ( Return, Valid startDate, Valid endDate ) ->
            onReturn startDate endDate

        _ ->
            default


isBookable : Booking -> Bool
isBookable =
    mapBooking
        { onOneWay = always True
        , onReturn =
            \startDate endDate ->
                endDate |> Date.isLaterThan startDate
        , default = False
        }

I would do something like this:

-- Not sure about the names
type ValidBooking
    = ValidOneWay Date
    | ValidReturn Date Date
    | Invalid


-- needs better name than `foo` :)
foo : Booking -> ValidBooking
foo { flight, start, end } =
    case ( flight, start, end ) of
        ( OneWay, Valid startDate, _ ) ->
            ValidOneWay startDate

        ( Return, Valid startDate, Valid endDate ) ->
            ValidReturn startDate endDate

        _ ->
            Invalid


isBookable : Booking -> Bool
isBookable booking =
    case foo booking of
        ValidOneWay _ ->
            True

        ValidReturn startDate endDate ->
            endDate |> Date.isLaterThan startDate

        Invalid ->
            False

I see the idea. Convert the Booking to another data structure that encodes the alternative structure I would want to pattern match over. My way uses functions and your way uses a data structure so it’s a sort of defunctionalization transformation. So what you suggest is another side of the same coin.

I don’t like the name ValidBooking though since it has within it a constructor named Invalid.

But the main question remains: What to name the functions?

One low-hanging improvement would be using a Maybe/Result instead

module Booking exposing (ValidBooking(..), toValid, ...)

type ValidBooking
    = ValidOneWay Date
    | ValidReturn { start : Date, end : Date }


toValid : Booking -> Maybe ValidBooking
toValid booking =
    case ( booking.flight, booking.start, booking.end ) of
        ( OneWay, Valid startDate, _ ) ->
            ValidOneWay startDate |> Just

        ( Return, Valid startDate, Valid endDate ) ->
            ValidReturn { start = startDate, end = endDate } |> Just

        _ ->
            Nothing

For isBookable I’d just case on the |> toValid or if you really need a bool use |> toValid |> Maybe.Extra.isJust

@lydell and @lue-bird thanks for the alternative implementation ideas.

As for the naming, I think I’ve settled on withBooking, withSelection, withSelected, and withCell.