Haskell 펑 터는 왜 대상 범주에 파생 유형 만 있습니까?


12

Haskell에서 Functor 타입 클래스 functor는 다음과 같이 정의됩니다 (예 : Haskell Wiki 참조 ).

class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b 

지금까지 내가 (만약 내가 잘못 나 수정하시기 바랍니다) 이해, 이러한 펑은 카테고리가 타입 생성자를 사용하여 구성 대상 범주, 예를 들면 같이 할 수 있습니다 [], Maybe다른 한편으로 등, 하나의 카테고리를 가진 펑의 생각 functor의 대상으로, 예를 들어 모든 Haskell 유형의 카테고리. 예를 들어 Intfunctor의 대상 범주에있는 객체 일 수도 있고 Maybe Int또는 아닙니다 [Int].

하스켈 펑터에 대한이 제한의 동기는 무엇입니까?


4
간단? 하스켈에는 퍼스트 클래스 타입 함수가 없으므로 모든 함수는 실제로 타입 생성자입니다.
Daniel Gratzer

2
@ jozefg : 내 무지를 용서하십시오 : "일등석 유형 함수"는 무엇입니까?
조르지오

4
그래서 그 기능에서 우리는 f오른쪽을 던지고 있습니까? 그리고 시나리오에서 f일반적인 Haskell 함수와 같고 유형을 유형에 매핑해야합니다. Haskell에서는 * -> *종류 생성자 가 유일하게 허용됩니다 . 타입 패밀리는 더 일반적이지만 항상 완전히 적용되어야합니다.
Daniel Gratzer


@ jozefg : 때때로이 질문에 대해 반복해서 생각합니다. 하스켈 제한이 펑터의 표현력에 영향을 미치지 않는다고 생각합니다. 예를 들어,리스트 functor에 동형 인 functor가 있지만 Int-> [Int]가 아니라 Int-> <type type no no constructor>을 사용하는 functor가 있다고 가정하자. 그런 다음 <type constructor을 사용하지 않는 fancy type>이 [Int]와 동형임을 증명할 수 있습니다. 따라서 형식 생성자를 사용하여 정의 된 개체를 선택하는 것이 편리하고 표현력을 희생하지 않습니다.
Giorgio

답변:


1

전혀 제한이 없습니다! 타입 생성자에 대한 범주 이론적 기초를 배우기 시작했을 때,이 점은 나를 혼란스럽게했습니다. 우리는 그것을 얻을 것입니다. 그러나 먼저 혼란을 해결해 보겠습니다. 이 두 인용문 :

이러한 functor는 유형 생성자를 사용하여 생성 된 범주를 대상 범주로만 가질 수 있습니다.

어떤 범주를 가진 functors를 functor의 대상으로 생각할 수 있습니다. 예 : 모든 Haskell 유형의 범주

functor가 무엇인지 오해하고 있거나 최소한 용어를 잘못 사용하고 있음을 보여줍니다.

펑 터는 카테고리를 구성 하지 않습니다 . 펑 터는 범주 매핑 입니다. 펑 터는 소스 카테고리의 객체 및 형태 (유형 및 기능)를 대상 카테고리의 객체 및 형태로 가져옵니다.

이것은 functor가 실제로 객체 쌍 F_obj 에 대한 맵핑 과 형태 F_morph 에 대한 맵핑 이라는 한 쌍 의 맵핑 임을 의미합니다 . Haskell 에서 functor 의 객체 부분 F_obj 는 형식 생성자의 이름 (예 :) 이고, morphism 부분은 함수입니다 ( 해당 표현식에서 언급 한 항목을 정렬하는 것은 Haskell 컴파일러의 책임입니다 ). 따라서 우리는 그것이 functor 라고 말할 수 없습니다 . 단지의 조합 과는 펑터이다. 여전히 사람들은 악용 표기법을 남용합니다. 프로그래머 는 functor를 호출 하는 반면, 범주 이론가는 functor의 두 부분을 모두 나타내는 데 동일한 기호를 사용합니다.ListfmapfmapListListfmapList

또한 프로그래밍에서 거의 모든 펑 터는 endofunctors입니다 . 즉, 소스 및 대상 범주는 동일합니다. 언어의 모든 유형 범주입니다. 이 범주를 Type 이라고하겠습니다 . endofunctor F유형 유형 매핑 T를 다른 유형 FT 와 함수 > S - T 다른 함수 FT -> FS . 이 매핑은 물론 functor 법률을 준수해야합니다.

사용 List예로서 : 우리는 타입 생성자가 List : Type -> Type, 그리고 기능을 fmap: (a -> b) -> (List a -> List b)함께 펑터를 형성하는 것이다. 티

정리할 마지막 요점이 있습니다. 쓰기는 List int하지 않습니다 만들 정수 목록의 새로운 유형입니다. 이 유형은 이미 존재 합니다. Type 카테고리의 객체였습니다 . List Int단순히 그것을 참조하는 방법입니다.

이제 functor가 유형을 말, Int또는으로 매핑 할 수없는 이유가 궁금 String합니다. 그러나 할 수 있습니다! 아이덴티티 펑터 만 사용하면됩니다. 범주 C 의 경우 항등 기능은 모든 객체를 자체에 매핑하고 형태를 자체에 매핑합니다. 이 매핑이 functor 법률을 만족하는지 확인하는 것은 간단합니다. Haskell에서 이것은 id : * -> *모든 유형을 자체에 매핑 하는 유형 생성자 입니다. 예를 들어로 id int평가됩니다 int.

또한 모든 유형을 단일 유형으로 매핑하는 상수 기능을 만들 수도 있습니다 . 예를 들어 functor ToInt : * -> *는 where ToInt a = int모든 유형에 대해 모든 형태 a를 정수 항등 함수에 매핑합니다. fmap f = \x -> x


답변 해 주셔서 감사합니다.이 질문은 2 년이 넘었습니다. "Functors는 카테고리를 구성하지 않습니다.": 나는 그렇게 말하지 않았다. 나는 목표 카테고리가 양식이 있어야합니다 경우 펑은 두 가지 범주를지도했다 f a, f이다, 내가 아는까지로, 타입 생성자를. 범주 이론에서 내가 기억하는 것에서, 이것은 일종의 정식 적 표현이어야합니다. 많은 감사합니다.
Giorgio

@Giorgio 으악, 나는 그것이 하하라는 것을 알지 못했습니다. 방금 "답변없는 질문"에 나타났습니다. "정식 표현"이 무슨 뜻인지 잘 모르겠습니다. 내가 아는 한 (그리고 여기서 틀릴 수있다), 펑터와 초기 / 터미널 객체 사이에는 관계가 없습니다.
gardenhead

나는 이것을 의미한다 : en.wikipedia.org/wiki/Initial_algebra (컴퓨터 과학에서 사용하기 참조). Haskell (대부분의) functors는 대수 데이터 형식으로 정의됩니다. 이러한 펑터의 대상은 초기 대수입니다. 초기 대수는 값 생성자를 사용하여 작성된 용어 집합과 동형입니다. 예 : 목록 []:. 나는 이것을 정식 표현으로 의미했습니다.
Giorgio

예, 초기 객체가 무엇인지, 귀납 데이터 유형은 카테고리의 F- 대수에서 초기 객체라는 것을 알고 있습니다. 많은 유형 생성자가 유도 적으로 정의되어있는 것이 맞습니다. 그러나 이것은 꼭 필요한 것은 아닙니다 . 예를 들어, 펑 (_, int)타입 얻어 a제품 유형 (a, int)및 함수 f : 'a -> 'b로는 g : 'a * int -> 'a * int유도하지 않다.
gardenhead

"... 기능 f : 'a -> 'b을 수행 g : 'a * int -> 'b * int합니까?
Giorgio
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.