ghci desugar 유형은 왜 패밀리를 나열하고 유형합니까? 선택적으로 비활성화 할 수 있습니까?


93

내 라이브러리의 유형 ghci 디스플레이를 가능한 한 직관적으로 만들려고 노력하고 있지만 더 고급 유형 기능을 사용할 때 많은 어려움이 있습니다.

파일에이 코드가 있다고 가정 해 보겠습니다.

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

import GHC.TypeLits

data Container (xs::[*]) = Container

ghci에서로드 한 다음 다음 명령을 입력합니다.

ghci> :t undefined :: Container '[String,String,String,String,String]

불행히도 ghci는 나에게 다소 추한 모습을 보여줍니다.

:: Container
       ((':)
          *
          String
          ((':)
             * String ((':) * String ((':) * String ((':) * String ('[] *))))))

ghci는 유형 수준 문자열의 설탕을 제거했습니다. ghci가 이것을 방지하고 나에게 예쁜 버전을주는 것을 방지하는 방법이 있습니까?


관련 메모에서 유형 수준 Replicate함수를 생성한다고 가정 해 보겠습니다.

data Nat1 = Zero | Succ Nat1

type family Replicate (n::Nat1) x :: [*]
type instance Replicate Zero x = '[]
type instance Replicate (Succ n) x = x ': (Replicate n x)

type LotsOfStrings = Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String

이제 ghci에게 다음을 사용하여 유형을 요청할 때 LotsOfStrings:

ghci> :t undefined :: Container LotsOfStrings

ghci는 훌륭하고 예쁜 결과를 제공합니다.

undefined :: Container LotsOfStrings

하지만 Replicated 버전을 요청하면

ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String)

ghci는 유형 동의어를 사용하지 않았을 때 유형 계열을 in으로 대체합니다.

:: Container
       ((':)
          *
          [Char]
          ((':)
             * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))

ghci가 유형 계열을 대체하지만 유형 동의어가 아닌 이유는 무엇입니까? ghci가 언제 대체를 수행할지 제어하는 ​​방법이 있습니까?


7
유형 동의어는 순전히 사람이 소비하도록 설계 되었기 때문에 유형 동의어를 그렇게 작성 /보기를 원했기 때문에 유형 동의어를 만들었다는 것을 인정하기 때문에 대체하지 않습니다. 유형 패밀리는 실제로 유형을 표시하지 않고 계산 / 추론하는 것이기 때문에 유형 패밀리로 대체합니다.
AndrewC 2013 년

문제에 대한 해결책은 귀하의 질문에 있습니다. 축약하려면 유형 동의어를 만드십시오.
AndrewC 2013 년

2
@AndrewC 방금 귀하의 의견과 관련된 또 다른 질문을 생각했습니다. 문자열 유형이 때때로 표시 [Char]되고 때로는 표시되는 이유는 무엇 String입니까?
Mike Izbicki 2013 년

1
나는 ghci가 소스에서 찾은 유형 동의어를 보존하려고 한다고 생각 합니다. 즉, 함수가 유형으로 선언 된 경우 String->String결과 유형은로 표시됩니다 String. 그러나 예에서와 같이 조각에서 유형을 구성해야하는 경우 "abc"(와 동일 'a':'b':'c':[]) 보존 할 동의어가 없습니다. 이것은 순수한 추측입니다.
n. '대명사'm.

4
@nm : GHC는 더 일반적인 유추 유형이 덜 일반적이고 명시 적으로 명명 된 유형 변수로 통합 될 때 유형 변수의 이름을 보존하려는 유사한 시도를합니다. 명시 적 유형 String이 유형 변수 f a또는으로 통합 [a]되면 [Char]유사한 이유로 나중에 다음과 같이 표시 될 것 입니다.
CA McCann 2013 년

답변:


2

내가 아는 해결 방법은 : kind를 사용하는 것입니다. 예를 들어

ghci> : kind (컨테이너 '[문자열, 문자열, 문자열, 문자열, 문자열])

제공 :

(컨테이너 '[문자열, 문자열, 문자열, 문자열, 문자열]) :: *

동안

ghci> : 종류! (컨테이너 '[문자열, 문자열, 문자열, 문자열, 문자열])

다음과 같이 인쇄됩니다.

컨테이너

(( ':)

  *
  [Char]
  ((':)
     * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))

물론 공식적으로는 ghci에게 다른 질문을 던지지 kind만 작동합니다. undefined ::어쨌든 사용 은 일종의 해결 방법이므로 이것이 충분할 것이라고 생각했습니다.


나는 undefined ::쉬운 예를 제공하기 위해서만 사용 했습니다. 실제 문제는 수천 가지 유형의 목록 유형이있는 오류 메시지를받을 때입니다. 인쇄하려면 페이지가 필요하며 구문 분석하기가 매우 어렵습니다.
Mike Izbicki 2013 년

예, 충분히 공평합니다. . 난 당신에게 더 나은 답변을 빚
user2141650

2

이는 곧 출시 될 GHC 7.8에서 수정되었습니다.

GHC 7.6은 데이터 유형이 PolyKinds를 사용하는 경우 종류를 인쇄합니다. 그래서 당신은 (':) * String ('[] *)단지 (':) String '[].

GHC 7.8에서는 종류가 더 이상 기본적으로 표시되지 않고 데이터 유형이 예상대로 목록으로 인쇄됩니다. 새 플래그 -fprint-explicit-kinds를 사용하여 GHC 7.6 에서처럼 명시적인 종류를 볼 수 있습니다 . 그 이유를 모르겠습니다. 아마도 명시적인 종류는 PolyKinds를 이해하는 데 도움이 될 것입니다.


0
import GHC.TypeLits

data Container (xs::[*]) = Container

ghci에서로드 한 다음 다음 명령을 입력합니다.

:t undefined :: Container '[String,String,String,String,String]

그래서...? 당신은 여전히 ​​내가 생각하는 desugared 결과를 얻습니다 String ((':) * String ((':) * String ((':) * ....
leftaroundabout
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.