대략적인 개요
함수형 프로그래밍에서 펑 터는 기본적으로 일반 단항 을 리프팅하는 구조입니다. 함수 (즉, 하나의 인수가있는 함수)를 새로운 유형의 변수 사이의 함수 . 일반 객체 사이에 간단한 함수를 작성하고 유지 관리하고 펑터를 사용하여 들어 올리고 복잡한 컨테이너 객체 사이에 함수를 수동으로 작성하는 것이 훨씬 쉽습니다. 또 다른 장점은 일반 기능을 한 번만 작성한 다음 다른 기능을 통해 재사용하는 것입니다.
펑터의 예로는 배열, "아마도"및 "둘 중 하나"펑터, 선물 (예 : 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 ).firstName
lastName
Maybe
// 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
. 예를 들어, Array
functor String
는 유형 [String]
( 유형 길이의 모든 문자열 배열 집합)에 유형 을 매핑하고 유형 을 Number
해당 유형 [Number]
(모든 숫자 배열 집합)에 설정합니다.
Functor 맵을 혼동하지 않는 것이 중요합니다
Array :: a => [a]
형태로 a -> [a]
. functor는 단순히 유형을 매핑 (연관)합니다a
을 유형 [a]
에 다른 것으로 . 각 유형이 실제로 요소 집합이라는 점은 여기서 관련이 없습니다. 대조적으로, 형태는 그 세트들 사이의 실제 기능입니다. 예를 들어, 자연적인 형태 (기능)가 있습니다
pure :: a -> [a]
pure = x => [x]
단일 값으로 해당 값을 갖는 1 요소 배열에 값을 보냅니다. 그 기능은Array
Functor 의 일부 아닙니다 ! 이 functor의 관점에서 볼 때 pure
다른 기능과 마찬가지로 특별한 기능은 없습니다.
반면에 Array
Functor는 두 번째 부분 인 형태 부분을 가지고 있습니다. 어떤 형태 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
예제 에서 쉽게 확인할 수 있습니다.