Deloryn / functional-programming-jargon

Jargon from the functional programming world in simple terms! My translation to Polish language. Original version:

Home Page:http://git.io/fp-jargons

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Słowniczek programowania funkcyjnego

Programowanie funkcyjne (FP) ma wiele zalet, w wyniku czego zyskuje popularność. Jednak każdy paradygmat programowania ma swój unikalny żargon i programowanie funkcyjne nie jest tutaj wyjątkiem. Poprzez dostarczenie Wam słowniczka, mamy nadzieję, że jego nauka będzie łatwiejsza.

Przykłady są przedstawione w JavaScript (ES2015). Dlaczego JavaScript?

Tam, gdzie to możliwe, dokument ten korzysta z terminów zdefiniowanych w Fantasy Land spec

Tłumaczenia

Spis treści

Arity

Arność. Liczba argumentów pobieranych przez funkcję. Pochodzi od słów takich jak unary, binary, ternary itd. To słowo wyróżnia się tym, że składa się z dwóch przyrostków ("-ary" i "-ity"). Np. dodawanie pobiera dwa argumenty, zatem jest zdefiniowane jako funkcja binarna lub jako funkcja o arności równej 2. Ludzie, którzy preferują greckie korzenie nazewnictwa (zamiast łacińskich), mogą czasem taką funkcję nazywać "diadyczną". Kiedy ilość argumentów funkcji może być różna, jest ona nazywana funkcją ze zmienną liczbą argumentów (variadic). Natomiast funkcja binarna musi mieć dwa i tylko dwa argumenty. Zobacz poniżej: Currying i Partial Application

const sum = (a, b) => a + b

const arity = sum.length
console.log(arity) // 2

// Arność funkcji sum wynosi 2

Higher-Order Functions (HOF)

Funkcja, która pobiera funkcję jako argument i/lub zwraca funkcję.

const filter = (predicate, xs) => xs.filter(predicate)
const is = (type) => (x) => Object(x) instanceof type
filter(is(Number), [0, '1', 2, null]) // [0, 2]

Closure

Closure to trwały zakres zmiennych dostępnych dla danej funkcji w momencie, kiedy została utworzona. Jest to ważne dla partial application.

const addTo = (x) => {
    return (y) => {
        return x + y
    }
}

Możemy wywołać addTo, podając pewną liczbę jako argument i otrzymamy funkcję z "wbudowaną" wartościąx.

var addToFive = addTo(5)

W tym przypadku x jest zawarte w closure addToFive z wartością 5. Możemy zatem wywołać addToFive z y i wtedy otrzymać pożądany wynik.

addToFive(3) // => 8

To działa, ponieważ zmienne, które są w zasięgu rodzica, nie są usuwane przez garbage-collectora tak długo, jak funkcja jest zachowana.

Closure są powszechnie wykorzystywane w event handlerach, dzięki czemu nadal mają dostęp do zmiennych zdefiniowanych u ich rodziców, kiedy są wywołane.

Dalsza lektura

Partial Application

Partial application polega na tym, że tworzymy nową funkcję, która z góry jest wypełniona niektórymi argumentami z funkcji bazowej.

// Pomocnik do tworzenia funkcji korzystających z partial application
// Pobiera funkcję i część argumentów
const partial = (f, ...args) =>
  // zwraca funkcję, która pobiera resztę argumentów
  (...moreArgs) =>
    // i wywołuje oryginalną funkcję posiadającą je wszystkie
    f(...args, ...moreArgs)

// Przykładowa funkcja
const add3 = (a, b, c) => a + b + c

// Wykorzystujemy partial application do "wbudowania" liczb 2 i 3 do funkcji add3. Daje to nam jednoargumentową funkcję.
const fivePlus = partial(add3, 2, 3) // (c) => 2 + 3 + c

fivePlus(4) // 9

Możesz także użyć Function.prototype.bind, by wykonać partial application dla funkcji w JS:

const add1More = add3.bind(null, 2, 3) // (c) => 2 + 3 + c

Partial application pomaga w tworzeniu prostszych funkcji poprzez "wbudowywanie" do nich danych dla funkcji bardziej złożonych. "Curried functions" automatycznie korzystają z partial application.

Currying

Proces zamiany funkcji, która pobiera wiele argumentów, w funkcję, która pobiera je wszystkie na raz.

Za każdym razem, kiedy funkcja jest wywołana, przyjmuje tylko jeden argument i zwraca funkcję, która pobiera jeden argument. Proces trwa do momentu, aż wszystkie argumenty zostaną przekazane.

const sum = (a, b) => a + b

const curriedSum = (a) => (b) => a + b

curriedSum(40)(2) // 42.

const add2 = curriedSum(2) // (b) => 2 + b

add2(10) // 12

Auto Currying

Przekształcanie funkcji, która pobiera wiele argumentów, w jedną, która ma taką cechę: jeśli podamy mniej argumentów niż wynosi jej arność, to zwraca funkcję, która pobiera resztę potrzebnych argumentów. Kiedy funkcja dostaje odpowiednią liczbę argumentów, to wtedy obliczana jest jej wartość.

lodash & Ramda mają funkcję curry, która działa w ten sposób.

const add = (x, y) => x + y

const curriedAdd = _.curry(add)
curriedAdd(1, 2) // 3
curriedAdd(1) // (y) => 1 + y
curriedAdd(1)(2) // 3

Dalsza lektura

Function Composition

Łączenie dwóch funkcji w trzecią funkcję tak, że wyjście (output) jednej funkcji jest wejściem (input) drugiej.

const compose = (f, g) => (a) => f(g(a)) // Definicja
const floorAndToString = compose((val) => val.toString(), Math.floor) // Użycie
floorAndToString(121.212121) // '121'

Continuation

W dowolnym miejscu w programie, ta część kodu, która pozostała jeszcze do wykonania, nazywana jest kontynuacją.

const printAsString = (num) => console.log(`Wynik: ${num}`)

const addOneAndContinue = (num, cc) => {
  const result = num + 1
  cc(result)
}

addOneAndContinue(2, printAsString) // 'Wynik: 3'

Kontynuacje często się pojawiają w programowaniu asynchronicznym, kiedy program potrzebuje zaczekać na otrzymanie danych, zanim będzie mógł kontynuować. Odpowiedź często jest przekazywana do reszty programu, która jest kontynuacją po jej otrzymaniu.

const continueProgramWith = (data) => {
  // Kontynuuję wykonywanie programu z tymi danymi
}

readFileAsync('path/to/file', (err, response) => {
  if (err) {
    // obsługa błędu
    return
  }
  continueProgramWith(response)
})

Purity

Czystość. Funkcja jest "czysta" (pure) wtedy, kiedy wartość przez nią zwracana jest zdeterminowana jedynie przez jej wartości wejściowe i nie ma przy tym żadnych "efektów ubocznych" (side effects).

const greet = (name) => `Hi, ${name}`

greet('Brianne') // 'Hi, Brianne'

W przeciwieństwie do poniższych przykładów:

window.name = 'Brianne'

const greet = () => `Hi, ${window.name}`

greet() // "Hi, Brianne"

Wynik powyższego przykładu bazuje na danych przechowywanych poza funkcją...

let greeting

const greet = (name) => {
  greeting = `Hi, ${name}`
}

greet('Brianne')
greeting // "Hi, Brianne"

... a w tym przykładzie modyfikowany jest stan na zewnątrz funkcji.

Side effects

Funkcja lub wyrażenie ma "efekt uboczny" (side effect) wtedy, kiedy oprócz zwracania wartości, zachodzi interakcja (odczyt lub zapis) z zewnętrznym, mutowalnym stanem.

const differentEveryTime = new Date()
console.log('IO is a side effect!')

Idempotent

Funkcja jest idempotentna wtedy, kiedy jej ponowne wywołanie na jej wartości (zobacz poniżej) nie zwraca innego wyniku.

f(f(x)) ≍ f(x)
Math.abs(Math.abs(10))
sort(sort(sort([2, 1])))

Point-Free Style

Sposób pisania funkcji, w którym nie mają one jawnej definicji argumentów, z jakich korzystają. Ten styl zazwyczaj potrzebuje wykorzystania currying lub innych funkcji wyższego rzędu. Styl znany również jako "Tacit programming".

// Na początku mamy:
const map = (fn) => (list) => list.map(fn)
const add = (a) => (b) => a + b

// Później:

// Nie w stylu points-free - `numbers` to argument jawny
const incrementAll = (numbers) => map(add(1))(numbers)

// W stylu points-free - lista jest argumentem niejawnym
const incrementAll2 = map(add(1))

incrementAll identyfikuje i korzysta z parametru numbers, więc to nie jest w stylu points-free. Funkcja incrementalAll2 jest napisana poprzez łączenie funkcji i wartości w taki sposób, że nie ma wzmianki o jej argumentach. Jest to zatem points-free.

Definicja funkcji napisanej w stylu points-free wygląda tak, jak normalne przypisania bez function czy =>.

Predicate

Predykat to funkcja, która zwraca albo prawdę (true), albo fałsz (false) dla podanej wartości. Powszechnym zastosowaniem predykatu jest callback dla array filter.

const predicate = (a) => a > 2

;[1, 2, 3, 4].filter(predicate) // [3, 4]

Contracts

Kontrakt określa obowiązki i gwarancje zachowania z funkcji lub wyrażenia w momencie wykonywania. Zachowuje się jak zestaw zasad, które są oczekiwane przez wejście i wyjście funkcji lub wyrażenia. Kiedykolwiek kontrakt zostanie naruszony, błędy są raportowane.

// Zdefiniuj nasz kontrakt : int -> int
const contract = (input) => {
  if (typeof input === 'number') return true
  throw new Error('Contract violated: expected int -> int')
}

const addOne = (num) => contract(num) && num + 1

addOne(2) // 3
addOne('some string') // Kontrakt naruszony: oczekiwany jest int -> int

Category

Kategoria (w teorii kategorii) jest kolekcją obiektów i morfizmów między nimi. W programowaniu, typy zwykle zachowują się jak obiekty, a funkcje jak morfizmy.

Aby kategoria była poprawna, muszą być spełnione 3 zasady:

  1. Musi być morfizm tożsamości, który mapuje obiekt do siebie. Gdzie a jest obiektem w jakiejś kategorii, tam musi być funkcja postaci: a -> a.
  2. Morfizmy muszą być "składalne". Gdzie a, b i c są obiektami jakiejś kategorii i f jest morfizmem postaci a -> b oraz g jest morfizmem postaci b -> c; g(f(fx)) musi być równoważne (g • f)(x).
  3. Kompozycja musi być asocjacyjna. f • (g • h) jest tym samym, co (f • g) • h

Ponieważ te zasady rządzą kompozycją na bardzo abstrakcyjnym poziomie, teoria kategorii jest świetna w odkrywaniu nowych sposobów komponowania rzeczy.

Dalsza lektura

Value

Value (wartość) to cokolwiek, co może zostać przypisane do zmiennej.

5
Object.freeze({name: 'John', age: 30}) // Funkcja `freeze` wymusza niemutowalność
;(a) => a
;[1]
undefined

Constant

Stała (constant) to zmienna, do której nie można już nic przypisać, gdy raz została już zdefiniowana.

const five = 5
const john = Object.freeze({name: 'John', age: 30})

Stałe cechuje [referential transparency](#referential-transparency. That is, they can be replaced with the values that they represent without affecting the result.

With the above two constants the following expression will always return true.

john.age + five === ({name: 'John', age: 30}).age + (5)

Functor

Obiekt, który implementuje funkcję map, która - działając na każdej wartości obiektu i tworząc nowy obiekt - trzyma się dwóch zasad:

Zachowuje tożsamość

object.map(x => x) ≍ object

Jest kompozycyjna (zobacz niżej)

object.map(compose(f, g)) ≍ object.map(g).map(f)

(f, g są dowolnymi funkcjami)

Powszechnym funktorem w JavaScripcie jest Array, ponieważ stosuje się do dwóch zasad funktora:

;[1, 2, 3].map(x => x) // = [1, 2, 3]

oraz

const f = x => x + 1
const g = x => x * 2

;[1, 2, 3].map(x => f(g(x))) // = [3, 5, 7]
;[1, 2, 3].map(g).map(f)     // = [3, 5, 7]

Pointed Functor

Obiekt z funkcją of, która umieszcza w nim pojedynczą wartość any.

ES2015 udostępnia Array.of, który zmienia tablice w pointed functory.

Array.of(1) // [1]

Lift

Lifting jest wtedy, kiedy bierzesz wartość i wrzucasz ją do obiektum tak jak w pointed functor. Jeśli liftingujesz funkcję do Applicative Functor, możesz sprawić, że zadziała także na tych wartościach, które są w tym funktorze.

Aby ułatwić korzystanie z funkcji na funktorach, niektóre implementacje mają funkcje lift lub liftA2.

const liftA2 = (f) => (a, b) => a.map(f).ap(b) // zauważ, że to jest `ap`, a nie `map`

const mult = a => b => a * b

const liftedMult = liftA2(mult) // ta funkcja działa teraz na funktorach tak, jak tablica

liftedMult([1, 2], [3]) // [3, 6]
liftA2(a => b => a + b)([1, 2], [3, 4]) // [4, 5, 5, 6]

Lifting to jednoargumentowa funkcja i używanie jej robi to samo, co map.

const increment = (x) => x + 1

lift(increment)([2]) // [3]
;[2].map(increment) // [3]

Referential Transparency

Referential transparency cechuje się tym, że wyrażenie może być podmienione na swoją wartość bez zmieniania zachowania programu.

Mamy funkcję greet:

const greet = () => 'Hello World!'

Każde wywołanie greet() może być zamienione na Hello World!, zatem greet jest referencyjnie transparentne.

Equational Reasoning

Kiedy aplikacja jest złożona z wyrażeń i pozbawiona side effectów, prawdy o systemie można wyprowadzić z jego części.

Lambda

Funkcja anonimowa, która może być traktowana jak wartość.

;(function (a) {
  return a + 1
})

;(a) => a + 1

Lambdy są często przekazywane jako argumenty do funkcji wyższego rzędu.

;[1, 2].map((a) => a + 1) // [2, 3]

Możesz przypisać wyrażenie lambda do zmiennej.

const add1 = (a) => a + 1

Lambda Calculus

Gałąź matematyki, która wykorzystuje funkcje, aby stworzyć uniwersalny model obliczeń.

Lazy evaluation

Lazy evaluation to mechanizm wartościowania typu call-by-need. Ewaluacja jest opóźniona do momentu, kiedy wartość jest potrzebna. W językach funkcyjnych pozwala to na struktury takie jak nieskończone listy, które normalnie nie byłyby dostępne w języku imperatywnym, gdzie sekwencjonowanie poleceń jest istotne.

const rand = function*() {
  while (1 < 2) {
    yield Math.random()
  }
}
const randIter = rand()
randIter.next() // Każde wywołanie zwraca losową wartość. Wyrażenie jest obliczane wtedy, kiedy jest potrzebne.

Monoid

Obiekt z funkcją, która "łączy" ten obiekt z innym obiektem tego samego typu.

Przykładem prostego monoidu jest dodawanie liczb:

1 + 1 // 2

W tym przypadku liczba jest obiektem, a + jest funkcją.

Musi również istnieć wartość tożsamości (identity value) - taka, że kiedy połączyć ją z wartością, to ona się nie zmienia. Zobacz poniżej:

Wartością tożsamości dla dodawania jest 0.

1 + 0 // 1

Jest także wymagane to, żeby grupowanie operacji nie wpływało na wynik (asocjatywność):

1 + (2 + 3) === (1 + 2) + 3 // true

Konkatenacja tablic również tworzy monoid:

;[1, 2].concat([3, 4]) // [1, 2, 3, 4]

W tym przypadku wartością tożsamości jest pusta tablica []

;[1, 2].concat([]) // [1, 2]

Jeśli mamy funkcje tożsamości oraz kompozycji (obie), one także tworzą monoid:

const identity = (a) => a
const compose = (f, g) => (x) => f(g(x))

foo jest dowolną jednoargumentową funkcją.

compose(foo, identity) ≍ compose(identity, foo) ≍ foo

Monad

Monada jest obiektem z funkcją of oraz chain. chain jest jak map z tym wyjątkiem, że "odgnieżdża" zagnieżdżony obiekt.

// Implementacja
Array.prototype.chain = function (f) {
  return this.reduce((acc, it) => acc.concat(f(it)), [])
}

// Użycie
Array.of('cat,dog', 'fish,bird').chain((a) => a.split(',')) // ['cat', 'dog', 'fish', 'bird']

// Różnica w stosunku do map
Array.of('cat,dog', 'fish,bird').map((a) => a.split(',')) // [['cat', 'dog'], ['fish', 'bird']]

of w innych językach funkcyjnych jest znane także jako return chain w innych językach jest znane także jako flatmap i bind

Comonad

Comonad to obiekt, który ma funkcje extract oraz extend.

const CoIdentity = (v) => ({
  val: v,
  extract () {
    return this.val
  },
  extend (f) {
    return CoIdentity(f(this))
  }
})

extract wydobywa wartość z funktora.

CoIdentity(1).extract() // 1

extend wykonuje funkcję na comonadzie. Funkcja ta powinna zwracać ten sam typ, jakim jest ten comonad.

CoIdentity(1).extend((co) => co.extract() + 1) // CoIdentity(2)

Applicative Functor

Funktorem aplikacyjnym jest obiekt z funkcją ap. Funkcja ta aplikuje funkcję z tego obiektu do wartości innego obiektu tego samego typu.

// Implementacja
Array.prototype.ap = function (xs) {
  return this.reduce((acc, f) => acc.concat(xs.map(f)), [])
}

// Pzykładowe użycie
;[(a) => a + 1].ap([1]) // [2]

Jest to użyteczne, kiedy masz dwa obiekty i chcesz zaaplikować funkcję binarną do ich zawartości.

// Tablice, które chcesz połączyć:
const arg1 = [1, 3]
const arg2 = [4, 5]

// łącząca funkcja - w tym przypadku trzeba zastosować currying, aby działało, jak trzeba
const add = (x) => (y) => x + y

const partiallyAppliedAdds = [add].ap(arg1) // [(y) => 1 + y, (y) => 3 + y]

W wyniku otrzymujesz tablicę funkcji, na której możesz wywołać ap, aby otrzymać wynik:

partiallyAppliedAdds.ap(arg2) // [5, 6, 7, 8]

Morphism

Morfizm to funkcja transformacji.

Endomorphism

Endomorfizm to funkcja, której typ wejściowy (input) jest taki sam, jak jej typ wyjścia (output).

// uppercase :: String -> String
const uppercase = (str) => str.toUpperCase()

// decrement :: Number -> Number
const decrement = (x) => x - 1

Isomorphism

Izomorfizm to para przekształceń między 2 typami obiektów, która jest strukturalna z natury i żadne dane nie są utracone.

Na przykład: współrzędne 2D mogłyby być przechowywane jako tablica [2,3] lub obiekt {x: 2, y: 3}.

// Dostarczenie funkcji do konwersji w obu kierunkach czyni je izomorficznymi.
const pairToCoords = (pair) => ({x: pair[0], y: pair[1]})

const coordsToPair = (coords) => [coords.x, coords.y]

coordsToPair(pairToCoords([1, 2])) // [1, 2]

pairToCoords(coordsToPair({x: 1, y: 2})) // {x: 1, y: 2}

Setoid

Setoid to obiekt, który ma funkcję equals, która może być użyta, aby porównać inne obiektu tego samego typu.

Spraw, żeby tablica była setoidem:

Array.prototype.equals = function (arr) {
  const len = this.length
  if (len !== arr.length) {
    return false
  }
  for (let i = 0; i < len; i++) {
    if (this[i] !== arr[i]) {
      return false
    }
  }
  return true
}

;[1, 2].equals([1, 2]) // true
;[1, 2].equals([0]) // false

Semigroup

Obiekt, który ma funkcję concat, która łączy go z innym obiektem tego samego typu.

;[1].concat([2]) // [1, 2]

Foldable

Obiekt, który ma funkcję reduce, która może przekształcić ten obiekt do jakiegoś innego typu.

const sum = (list) => list.reduce((acc, val) => acc + val, 0)
sum([1, 2, 3]) // 6

Lens

Lens to struktura (często obiekt lub funkcja), która łączy w parę getter oraz niemutujący setter dla jakiejś struktury danych.

// Korzystamy z [Ramda's lens](http://ramdajs.com/docs/#lens)
const nameLens = R.lens(
  // getter dla właściwości "name" obiektu
  (obj) => obj.name,
  // setter dla właściwości "name"
  (val, obj) => Object.assign({}, obj, {name: val})
)

Posiadanie pary gettera i settera dla danej struktury daje kilka istotnych możliwości.

const person = {name: 'Gertrude Blanch'}

// wywołaj getter
R.view(nameLens, person) // 'Gertrude Blanch'

// wywołaj setter
R.set(nameLens, 'Shafi Goldwasser', person) // {name: 'Shafi Goldwasser'}

// odpal funkcję na wartości w strukturze
R.over(nameLens, uppercase, person) // {name: 'GERTRUDE BLANCH'}

Lensy są także kompozycyjne. To pozwala na proste, niemutowalne aktualizacje głęboko zagnieżdżonych danych.

// Ten lens skupia się na pierwszym elemencie niepustej tablicy
const firstLens = R.lens(
  // pobierz pierwszy element tablicy
  xs => xs[0],
  // niemutujący setter dla pierwszego elementu tablicy
  (val, [__, ...xs]) => [val, ...xs]
)

const people = [{name: 'Gertrude Blanch'}, {name: 'Shafi Goldwasser'}]

// Poimo tego, co być może zakładasz, lensy komponują się od lewej do prawej.
R.over(compose(firstLens, nameLens), uppercase, people) // [{'name': 'GERTRUDE BLANCH'}, {'name': 'Shafi Goldwasser'}]

Inne implementacje:

Type Signatures

Funkcje w JavaScripcie często zawierają komentarze, które wskazują na typy ich argumentów oraz zwracanych wartości.

W społeczności występują spore różnice, ale często można zaobserwować te wzorce:

// nazwaFunkcji :: typPierwszegoArgumentu -> typDrugiegoArgumentu -> typZwracany

// add :: Number -> Number -> Number
const add = (x) => (y) => x + y

// increment :: Number -> Number
const increment = (x) => x + 1

Jeśli argumentem jest funkcja, to pisana jest wtedy w nawiasie.

// call :: (a -> b) -> a -> b
const call = (f) => (x) => f(x)

Litery a, b, c, d są używane do oznaczenia, że argument może być dowolnego typu. Następująca wersja map pobiera funkcję (która przekształca wartość pewnego typu a do innego typu b) i tablicę wartości typu a, i finalnie zwraca tablicę wartości typu b.

// map :: (a -> b) -> [a] -> [b]
const map = (f) => (list) => list.map(f)

Dalsza lektura

Algebraic data type

Typ złożony, stworzony z umieszczenia różnych typów razem. Dwie powszechne klasy typów algebraicznych to sum oraz product.

Sum type

Jest to połączenie dwóch typów w jeden nowy. Nazwa "sum" wzięła się z tego, że liczba możliwych wartości w typie wynikowym jest sumą typów wejściowych.

JavaScript nie ma tego rodzaju typów, ale możemy skorzystać zSetów, by niejako je "udawać":

// wyobraź sobie, że zamiast setów mamy tu typy, które mogą posiadać tylko takie wartości
const bools = new Set([true, false])
const halfTrue = new Set(['half-true'])

// Typ weakLogic zawiera sumę wartości z bools i halfTrue
const weakLogicValues = new Set([...bools, ...halfTrue])

Typy sum są czasem nazywane typami unii (union types), dyskryminowanch unii (discriminated unions) lub unii oznaczonych (tagged unions).

W JavaScripcie istnieje kilka bibliotek, które pomagają przy definiowaniu i korzystaniu z unii.

Flow ma union types, a TypeScript ma Enums, które spełniają tę samą rolę.

Product type

Product type łączy typy razem w sposób, który prawdopodobnie jest Ci bardziej znany:

// point :: (Number, Number) -> {x: Number, y: Number}
const point = (x, y) => ({ x, y })

Nazwa wzięła się stąd, że wszystkie możliwe wartości tej struktury danych są produktem innych wartości. Wiele języków ma typ "tuple", który jest najprostszym sformułowaniem product type.

Zobacz także Teoria setów.

Option

Opcja to sum type z dwoma przypadkami, zwykle nazywanymi Some i None.

Opcja jest użyteczna w komponowaniu funkcji, które mogą nie zwracać wartości.

// Definicja naiwna

const Some = (v) => ({
  val: v,
  map (f) {
    return Some(f(this.val))
  },
  chain (f) {
    return f(this.val)
  }
})

const None = () => ({
  map (f) {
    return this
  },
  chain (f) {
    return this
  }
})

// maybeProp :: (String, {a}) -> Option a
const maybeProp = (key, obj) => typeof obj[key] === 'undefined' ? None() : Some(obj[key])

Użyj chain do ustawienia kolejności funkcji, które zwracają Option.

// getItem :: Cart -> Option CartItem
const getItem = (cart) => maybeProp('item', cart)

// getPrice :: Item -> Option Number
const getPrice = (item) => maybeProp('price', item)

// getNestedPrice :: cart -> Option a
const getNestedPrice = (cart) => getItem(cart).chain(getPrice)

getNestedPrice({}) // None()
getNestedPrice({item: {foo: 1}}) // None()
getNestedPrice({item: {price: 9.99}}) // Some(9.99)

Option jest znane również jako Maybe. Some jest czasami nazywane Just. None jest czasem nazywane Nothing.

Biblioteki programowania funkcyjnego w JavaScripcie


P.S: To repo się udało dzięki udziałowi różnych ludzi!

About

Jargon from the functional programming world in simple terms! My translation to Polish language. Original version:

http://git.io/fp-jargons

License:MIT License