2015-10-16 2 views
3

Иногда мне нужно написать функцию, которая может иметь или не иметь эффекта.Идиома для описания возможности эффекта

Есть ли функциональная (или иная) идиома для описания такого положения дел? Префикс maybe описывает это, но есть ли что-то идиоматическое?

Например:

function maybe(guardCb) { 
    return function(cb) { 
    return function() { 
     if(guardCb.apply(this, arguments)) { 
     return cb.apply(this, arguments); 
     } 
    } 
    }; 
} 

function isFoo(args) { 
    return args.isFoo(); 
} 

function doSomething(args) { 
    return foo.bar(args.bam); 
} 

maybe(isFoo)(doSomething)(args); 

Я сознаю, может быть монады, но мне кажется, отличается от этого.

+0

Как и я, я напишу условие 'doSomething()' получение вызова в имя функции. –

+1

Вы ищете соглашения об именах или технику программирования? – Bergi

+0

Техника программирования Я полагаю. Меня интересует реализация условного в «функциональном» стиле. – Ben

ответ

2

Это просто чистая функция. Эквивалентный код Haskell:

maybe :: (a -> Bool) -> (a -> b) -> a -> Maybe b 
maybe p f x = if p x then Just (f x) else Nothing 

example = maybe p f x 

Для этой функции нет специального названия. Тем не менее, она может быть упрощена:

maybe :: Bool -> b -> Maybe b 
maybe b y = if b then Just y else Nothing 

example = (maybe <$> p <*> f) x 

Обратите внимание, что p :: a -> Bool, f :: a -> b и maybe p f :: a -> Maybe b все имеют одну общую черту (т.е. ((->) a)). Это интерфейс Reader, и его можно абстрагировать, используя класс типа Applicative, что и я сделал.

Однако, это не очень хороший код. Лучше абстракция будет:

maybe :: (a -> Maybe b) -> (b -> c) -> a -> Maybe c 
maybe p f = fmap f . p 

Обратите внимание, что p :: a -> Maybe b теперь Kleisli arrow вместо простой функции предиката. Мы переместили условную логику из функции maybe. В JavaScript код будет теперь:

isFoo(args).map(doSomething); 

Все, что вам нужно сделать, это определить тип данных Maybe и реализовать свой Functor интерфейс:

function Maybe(constructor) { 
    this.constructor = constructor || this; 
} 

var Nothing = new Maybe; 

function Just(value) { 
    var maybe = new Maybe(Just); 
    maybe.value = value; 
    return maybe; 
} 

Maybe.prototype.map = function (functor) { 
    switch (this.constructor) { 
    case Nothing: return Nothing; 
    case Just: return Just(functor(this.value)); 
    } 
}; 

Конечно, вам также необходимо будет пересмотреть isFoo, как следующим образом:

function isFoo(args) { 
    return args.isFoo() ? Just(args) : Nothing; 
} 

функция doSomthing может оставаться как есть. Надеюсь, это поможет.

Идиома, которую вы ищете, является интерфейсом Functor.

+0

Какое имя принадлежит к этой области? Теория языка? Вы узнали об этом из Хаскелла или академически? – Ben

+0

Это [теория категорий] (https://en.wikipedia.org/wiki/Category_theory), ветвь математики. Теория категорий обобщает математику. Однако это полезно и для программирования (для обобщения различных общих интерфейсов, таких как «Functor» и «Monad»). Поэтому он широко используется в Haskell, и вы изучаете много теорий категорий, когда вы изучаете Haskell. –

0

Я думаю, что слово «возможно» подходит, чтобы намекнуть о влиянии функции.

correctPossibleError() 

handlePossibleNameChange() 

erasePossibleOuterCircle() 

includePossibleMatches() 
Смежные вопросы