2017-10-15 1 views
2

자바 스크립트에서 응용 펑터를 사용하는 방법을 배우려하고 ap 메서드를 발견했습니다. 나는과 같이 세 가지 배열을 결합하여 사용하는 것을 시도하고있다 :Ramda 's ap와 관련없는 어플리케이션 펑터는 무엇입니까?

const products = ['teeshirt', 'sweater'] 
const options = ['large', 'medium', 'small'] 
const colors = ['red', 'black'] 

그래서 documentation마다 나는이 시도하고 같이

const buildMerch = product => option => color =>`${product}-${option}-${color}` 

const merchandise = R.ap([buildMerch], [products, options, colors]) 

을하지만이 다시 세 가지 기능 저를주고있다 :

[function (option) { 
    return function (color) { 
    return product + '-' + option + '-' + color; 
    }; 
}, function (option) { 
    return function (color) { 
    return product + '-' + option + '-' + color; 
    }; 
}, function (option) { 
    return function (color) { 
    return product + '-' + option + '-' + color; 
    }; 
}] 

... 예상 한 배열 조합 결과 대신 ...

["teeshirt- large-red", "teeshirt- large-black", "teeshirt- medium-red", "teeshirt- medium-black", "teeshirt- small-red", "teeshirt- small-black", "sweater- large-red", "sweater- large-black", "sweater- medium-red", "sweater- medium-black", "sweater- small-red", "sweater- small-black"] 

내가 뭘 잘못하고 있니? 이 문제를 어떻게 해결할 수 있습니까? https://jsbin.com/fohuriy/14/edit?js,console

답변

3

ap가 문서마다, 값리스트 기능의 목록을 적용 여기

이 문제와 jsbin이다.

buildMerch :: String -> String -> String -> String 

ap의 가장 간단한 종류 map입니다 : 귀하의 기능 buildMerch 다음과 같은 "유형"을 포함하는 실용적 펑, 우리가 얻을 :

배열
pure f <*> a 
    ====== 
map f a 

, purex => [x]입니다. 그래서, 인수 목록을 통해 매핑 buildMerch으로

R.ap([buildMerch], [foo, bar, baz]) 
    ====== 
R.map(buildMerch, [foo, bar, baz]) 

, 우리는 부분적으로 문제의 배열에 적용된다. 당신이 원하는 것을 표현은 다음과 같습니다

const merchandise = R.ap(R.ap(R.map(buildMerch, products), options), colors); 

첫째, 우리는 제품의 배열을 통해 buildMerch 매핑합니다. 이것은 두 개의 인수, 즉 [String -> String -> String]을 취하는 배열을 제공합니다. 그런 다음 R.ap을 사용하여 options :: [String]과 결합하여 첫 번째 배열의 각 함수를 options 배열의 각 인수와 함께 적용합니다. 이제 [String -> String]이 있고 마지막으로 R.apcolors으로 원하는 문자열의 최종 배열을 얻습니다.

+2

좋은 설명, 감사합니다! –

1

AP은 값 목록에 함수 목록을 적용합니다. 귀하의 경우 지정된 배열의 모든 요소가 buildMerch이고, 배열은 products이고 그 다음은 options이고 그 뒤에는 colors이며 배열 내의 모든 조합이 아닌 배열을 호출합니다. 이것은 세 개의 인수를 예상하는 메소드 서명과 일치하지 않습니다.

1

이 문제를 해결하는 또 다른 방법은 ap을 기본 javascript Array에 추가하는 것입니다. 이 방법으로 Array를 응용 펑터로 바꾸고 라이브러리를 사용할 필요가 없으며 다른 응용 펑터와 동일한 인터페이스에서 사용할 수 있습니다.

// add ap 
Array.prototype.ap = function(anotherArray) { 
    return this.map(el => 
    anotherArray.map(el) 
).flatten(); 
}; 

이것은 평평한 (또는 '참여') 것에 의존합니다.이제

// add flatten 
Array.prototype.flatten = function() { 
    let results = []; 
    this.forEach(subArray => { 
    subArray.forEach(item => { 
     results.push(item); 
    }); 
    }); 
    return results; 
}; 

:

const products = ['teeshirt', 'sweater']; 
const options = ['large', 'medium', 'small']; 
const colors = ['red', 'black']; 
const buildMerch = product => option => color =>`${product}-${option}-${color}`; 

const merchandise = products.map(buildMerch).ap(options).ap(colors); 

이제 당신은 또한 세 가지를 들어 올려 수 :

const liftA3 = (fn, functor1, functor2, functor3) => 
    functor1.map(fn).ap(functor2).ap(functor3); 

liftA3(buildMerch, products, options, colors) // also returns merchandise 
관련 문제