2017-09-25 10 views
18

그러나GHC 튜플의 크기가 62 인 이유는 무엇입니까? 하여 <a href="https://www.haskell.org/onlinereport/basic.html" rel="noreferrer">Haskell 98 report</a>에서

There is no upper bound on the size of a tuple, but some Haskell implementations may restrict the size of tuples, and limit the instances associated with larger tuples. However, every Haskell implementation must support tuples up to size 15, together with the instances for Eq, Ord, Bounded, Read, and Show. (...)

, 잘 GHC가 62보다 큰 크기의 튜플을 지원하지 않는 것으로 알려져 여기에 내가 GHCi의 크기 (63)의 튜플 만들려고 할 때 발생하는 내용은 다음과 같습니다

<interactive>:1:1: error: 
    A 63-tuple is too large for GHC 
     (max size is 62) 
     Workaround: use nested tuples or define a data type 

이것이 Haskell 98 사양과 일치하며 크기가 62보다 큰 튜플은 매우 불필요한 것으로 생각되지만 이것이 GHC에서와 같은 이유는 정확히 이해할 수 없습니다.


요약하면 :

  • 왜 튜플 크기 제한이 전혀 있는가?
  • 왜 크기 제한이 특별히 62입니까? 또한

:

  • 왜 이것은 단지 이후 GHC 6.12.2과에서의 경우?
  • 다른 저명한 하스켈 구현 방식이이를 수행합니까? 그 이유는 무엇입니까?
+1

더 높은 카디널리티의 튜플은 하스켈에서 자주 사용되지 않습니다. 우리가 구조적으로 (공동) 재귀 적 데이터 유형으로 작업하기를 선호하기 때문입니다. 나는 3 튜플보다 큰 것을 사용했을 때를 생각할 수 없다. 이렇게하면 코드 냄새 IMHO 것입니다. GHC의 제안도 유효합니다. 필드가 62 개 이상인 제품 유형이 필요하다면 직접 '데이터'레코드를 정의 할 가치가 있습니다. – cdk

+4

크기 제한이 있으며 왜 62입니까? [Manuel Chakravarty의 말] (https://hackage.haskell.org/package/ghc-prim-0.5.1.0/docs/src/GHC.Tuple.html#%28%2C%2C%2C%2C%2C%) 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 2C % 29). 튜플이 클수록 세그멘테이션 오류가 발생합니다. GHC 6에서이 한계는 없었습니다. 그 이후로 무슨 일이 있었는지 알아내는 것은 재미있을 것입니다 ... – Alec

+0

@Alec 사실,이 62 필드 한도는 GHC 6.12.2부터입니다. 이 질문에 추가 할 수 있습니다. 편집 : 추가 – AJFarmar

답변

33

나는이 추측의 변화가 타이밍이 잘못되었다고 생각한다. 첫째, 내가 알 수있는 한도는 LONG 6.12.1 이전부터 존재했습니다. 버전 5.02.2에서 TraC#98 from November 2002에서 알 수있는 바와 같이, 제한은 37 (대신 62), 그리고 더 큰 튜플을 사용하려고하면 이상한 메시지 생성 :

Switches_tupel.lhs:1: 
Failed to find interface decl for 
`PrelTup.(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)' 
    from module `PrelTup' 

시몬 페이튼 존스하여 버그 수정을 컴파일러가 컴파일 파이프 라인에서 더 일찍 크기를 확인하고 더 좋은 오류 메시지 (Git 커밋 b44c6881에서 볼 수 있음)를 생성합니다. 이 커밋이 이루어지기 전까지 한계는 이미 37에서 62로 증가했습니다. GHC 5.04는 62 튜플 한도와 더 나은 오류 메시지와 함께 출시되었습니다 (Git commit 9af77fa4, Template Haskell 작업을 HEAD에 통합 시켰습니다).

원래 TraC# 98 버그가 한계를 설명하는 이유라고 생각합니다. ghc/compiler/prelude/TysWiredIn.hs에서 튜플 타입 데이터 생성자의 세트는 미리 할당되어 mAX_TUPLE_SIZE 문제의 62 튜플 한계

boxedTupleArr, unboxedTupleArr :: Array Int (TyCon,DataCon) 
boxedTupleArr = listArray (0,mAX_TUPLE_SIZE) [mk_tuple Boxed i 
        | i <- [0..mAX_TUPLE_SIZE]] 
unboxedTupleArr = listArray (0,mAX_TUPLE_SIZE) [mk_tuple Unboxed i 
        | i <- [0..mAX_TUPLE_SIZE]] 

.

tupleTyCon :: Boxity -> Arity -> TyCon 
tupleTyCon sort i | i > mAX_TUPLE_SIZE 
       = fst (mk_tuple sort i) -- Build one specially 
tupleTyCon Boxed i = fst (boxedTupleArr ! i) 
tupleTyCon Unboxed i = fst (unboxedTupleArr ! i) 

을이 시몬 전에 할하는 데 사용되는 컴파일러 오류 메시지가 추가 된 것입니다 그러나, 실제로 사용이 미리 할당 된 배열이 수요에 더 큰 생성자를 생성 드리겠습니다 기능은 ("특별히 하나를 구축") 5.04 - 그것은 특별히 하나를지었습니다.

불행하게도 컴파일러가 ghc/libraries/ghc-prim/GHC/Tuple.hs에 주어진 목록의 너무 큰 튜플에 대한 인터페이스 정의를 찾지 못했을 때 나중에 컴파일 프로세스에서 오류가 발생했습니다 (segfault가 아니라 단지 오류).TysWiredIn.hs에있는 (다소 오래된) 주석에 따르면, Tuple.hs의 선언은 터플 생성자에 대한 정보 테이블과 엔트리 코드를 생성하는 데 사용됩니다. 이론적으로는 임의의 큰 튜플에 대해 프로그래밍 방식으로 생성 될 수도 있습니다.

그래서 현대 GHC는 무엇을 의미합니까? 컴파일러가 임의로 큰 튜플을 생성 할 준비가되어있는 경우에도 동일한 기술상의 이유 때문에 일치하는 선언이 필요하다는 제한이 있습니다 (.../GHC/Tuple.hs).

터플 길이 검사가 비활성화 된 소스에서 GHC를 컴파일하여 몇 가지 실험을 실행했습니다. 결과 컴파일러 성공적으로 컴파일하고 100- 튜플 다음 프로그램을 실행합니다 :

a = (False,...,False) -- imagine 100 Falses 
main = let (x,_,...,_) = a 
     in print x 

및 "False"가 인쇄됩니다.

a = (False,...,False) -- imagine 100 Falses 
main = let (_,...,_,x) = a 
     in print x 

그러나 프로그램 :

[1 of 1] Compiling Main    (Tuple.hs, Tuple.o) 
Linking Tuple ... 
Tuple.o(.data+0x0): error: undefined reference to 'ghczmprim_GHCziTuple_Z100T_con_info' 
collect2: error: ld returned 1 exit status 
`gcc' failed in phase `Linker'. (Exit code: 1) 

I :

a = (False,...,False) -- imagine 100 Falses 
main = let (x,_,...,_,y) = a 
     in print (x,y) 

이 연결 오류로 실패 나도 같은 튜플의 마지막 요소를 잡아 그것을 수정 때 괜찮 았는데 처음 두 프로그램에서는 컴파일러가 누락 된 생성자에 대한 참조를 최적화했지만 최종 프로그램에 필요하다고 생각합니다. Tuple.hs에 100- 튜플에 대한 선언을 추가하고 컴파일러를 다시 작성한 후에 세 가지 프로그램 모두 컴파일되어 제대로 실행되었습니다. Tuple.hs 튜플의 수동 구성리스트를 컴파일 요컨대

는 크기 (62)까지 튜플들을 지원하는데 필요한 데이터 구조를 생성하고, 아무도 Tuple.hs 버팀목 독립적으로 데이터 구조의 생성을 다시 구현할 충분히 동기 없었다 . 만약 그렇다면, GHC는 아마도 임의의 크기의 튜플을 지원할 것입니다.

마누엘의 segfault (이 질문에 대한 주석 중 하나 참조)에 대한 Tuple.hs의 메모는 libraries/base/Data/Tuple.hs으로 확인 된 2001 년 7 월 날짜이므로 날짜와 관련이 없습니다. 온실 가스 6.12.1. 이 문제는 아마도 Simon에 의해 max가 62로 설정되었지만, 더 이상 현대 GHC에는 적용되지 않는 것으로 보입니다.

+1

흥미 롭습니다. 튜플 크기에 대한 제한을 해제하는 것은 어렵지 않아야하는 것처럼 들립니다. 나는 이것을 GHC 내부에서 놀기의 한 방법으로 시도 할 것입니다. – Alec

+0

Bravo. 언젠가는 GHC 역사에 대한 책에 귀하의 연구가 포함되기를 바랍니다. : D –

+1

나는 이것이 아주 간단하다는 것을 확신하지 못한다. 문제는 필요한 정보 테이블을 선언하기위한 장소가 필요하다는 것입니다. 필요한 모든 모듈에서 재생성하면 모든 종류의 것들이 중단됩니다 (예 : 프로파일 링). 난 당신이 중복 테이블을 제거하기 위해 링커에 의지 할 수있을 것 같아요하지만 이것은 현재 우리가 할 일이 아닙니다. – bgamari