대략적인 개요
함수형 프로그래밍에서 펑 터는 기본적으로 일반 단항 을 리프팅하는 구조입니다. 함수 (즉, 하나의 인수가있는 함수)를 새로운 유형의 변수 사이의 함수 . 일반 객체 사이에 간단한 함수를 작성하고 유지 관리하고 펑터를 사용하여 들어 올리고 복잡한 컨테이너 객체 사이에 함수를 수동으로 작성하는 것이 훨씬 쉽습니다. 또 다른 장점은 일반 기능을 한 번만 작성한 다음 다른 기능을 통해 재사용하는 것입니다.
펑터의 예로는 배열, "아마도"및 "둘 중 하나"펑터, 선물 (예 : https://github.com/Avaq/Fluture 참조 ) 및 기타 여러 가지가 있습니다.
삽화
이름에서 성 전체 이름을 구성하는 함수를 고려하십시오. 우리는 이것을 fullName(firstName, lastName)두 개의 인수의 함수 처럼 정의 할 수 있지만, 하나의 인수의 함수만을 다루는 함수에는 적합하지 않습니다. 이를 해결하기 위해 단일 인수로 모든 인수를 수집하여 name이제 함수의 단일 인수가됩니다.
// In JavaScript notation
fullName = name => name.firstName + ' ' + name.lastName
이제 배열에 많은 사람이 있다면 어떨까요? 수동으로 목록을 살펴 보는 대신 짧은 한 줄의 코드로 배열에 제공된 방법을 fullName통해 단순히 함수 를 재사용 할 수 있습니다 map.
fullNameList = nameList => nameList.map(fullName)
그리고 그것을 사용하십시오
nameList = [
{firstName: 'Steve', lastName: 'Jobs'},
{firstName: 'Bill', lastName: 'Gates'}
]
fullNames = fullNameList(nameList)
// => ['Steve Jobs', 'Bill Gates']
우리의 모든 항목이 속성 과 속성을 nameList모두 제공하는 객체 일 때마다 작동 합니다. 그러나 일부 물체가 그렇지 않은 경우 (또는 전혀 물체가 아닌 경우) 어떻게해야합니까? 오류를 피하고 코드를 더 안전하게 만들기 위해 객체를 유형 으로 래핑 할 수 있습니다 (예 : https://sanctuary.js.org/#maybe-type ).firstNamelastNameMaybe
// function to test name for validity
isValidName = name =>
(typeof name === 'object')
&& (typeof name.firstName === 'string')
&& (typeof name.lastName === 'string')
// wrap into the Maybe type
maybeName = name =>
isValidName(name) ? Just(name) : Nothing()
여기서 Just(name)유효한 이름 만 가진 컨테이너이며 Nothing()다른 모든 것에 사용되는 특별한 값입니다. 이제 인수의 유효성을 검사하기 위해 방해하거나 잊어 버리는 대신이 방법을 fullName다시 기반으로 다른 단일 코드 행으로 원래 함수를 재사용 (리프팅) 할 수 있습니다. map이번에는 Maybe 유형에 제공되었습니다.
// Maybe Object -> Maybe String
maybeFullName = maybeName => maybeName.map(fullName)
그리고 그것을 사용하십시오
justSteve = maybeName(
{firstName: 'Steve', lastName: 'Jobs'}
) // => Just({firstName: 'Steve', lastName: 'Jobs'})
notSteve = maybeName(
{lastName: 'SomeJobs'}
) // => Nothing()
steveFN = maybeFullName(justSteve)
// => Just('Steve Jobs')
notSteveFN = maybeFullName(notSteve)
// => Nothing()
카테고리 이론
범주 이론 의 Functor 는 형태 의 구성을 고려한 두 범주 사이의 맵입니다. 안에 컴퓨터 언어 , 관심의 주요 카테고리는 누구 하나 인 객체 입니다 유형 그 (값의 특정 세트), 및 morphisms 있는 기능을 f:a->b하나 개의 유형에서 a다른 유형으로는 b.
예를 들어, 가지고 a로 String유형, b숫자 유형 및 f길이에 캐릭터를 매핑하는 기능입니다 :
// f :: String -> Number
f = str => str.length
여기 a = String 에는 모든 문자열 b = Number세트와 모든 숫자 세트가 표시됩니다. 그런 의미에서, 두 a과 b의 오브젝트 표현 집합 카테고리 (가깝게 차이가 중요하지 않은 여기 인 상태 유형의 카테고리에 관한 것이다). 세트 카테고리에서 두 세트 사이의 형태 는 정확히 첫 번째 세트에서 두 번째 세트까지의 모든 기능입니다. f여기서 길이 함수 는 문자열 집합에서 숫자 집합으로의 형태입니다.
우리는 집합 범주 만 고려하기 때문에 관련 함수 는 그 자체에서 객체를 객체로, 형태를 특정 대 수법 을 만족시키는 형태로 보내는 맵입니다.
예: Array
Array많은 것을 의미 할 수 있지만 단 하나의 유형은 Functor입니다. 유형 구조 a는 유형 [a]을 모든 유형 의 배열 유형 에 매핑 합니다.a . 예를 들어, Arrayfunctor String 는 유형 [String]( 유형 길이의 모든 문자열 배열 집합)에 유형 을 매핑하고 유형 을 Number해당 유형 [Number](모든 숫자 배열 집합)에 설정합니다.
Functor 맵을 혼동하지 않는 것이 중요합니다
Array :: a => [a]
형태로 a -> [a]. functor는 단순히 유형을 매핑 (연관)합니다a 을 유형 [a]에 다른 것으로 . 각 유형이 실제로 요소 집합이라는 점은 여기서 관련이 없습니다. 대조적으로, 형태는 그 세트들 사이의 실제 기능입니다. 예를 들어, 자연적인 형태 (기능)가 있습니다
pure :: a -> [a]
pure = x => [x]
단일 값으로 해당 값을 갖는 1 요소 배열에 값을 보냅니다. 그 기능은Array Functor 의 일부 아닙니다 ! 이 functor의 관점에서 볼 때 pure다른 기능과 마찬가지로 특별한 기능은 없습니다.
반면에 ArrayFunctor는 두 번째 부분 인 형태 부분을 가지고 있습니다. 어떤 형태 f :: a -> b를 형태 로 매핑 하는가[f] :: [a] -> [b] ?
// a -> [a]
Array.map(f) = arr => arr.map(f)
다음 arr타입의 값으로 임의의 길이의 임의의 어레이이며 a, 그리고 arr.map(f)타입의 값과 동일한 길이의 배열 b엔트리 적용한 결과이다 f의 엔트리들 arr. 그것을 functor로 만들려면, 정체성을 정체성에, 작곡을 작곡에 매핑하는 수학적 법칙이 있어야하며,이 Array예제 에서 쉽게 확인할 수 있습니다.