5

'`#에 대한'일치 할 수 없습니다 이 중 Exp (Show 인스턴스가 있음)을 얻으려고했다. 나는 응용 프로그램에서 haskell 유형에 대한 정보를 삽입하여 문자열이 아닌 실제 데이터로 사용할 수 있도록이 작업을 수행하고 있습니다.종류`* 도대체 여기 무슨 일

내 목표는 다음과 같다 :

info :: Info 
info = $(reify ''Show >>= dataToExpQ (const Nothing)) 

난 정말 그 오류 메시지를 이해하지 못하고, '#'은 어쨌든 무엇인가? #이있는 경우 # -> # 또는 * -> #도 있습니까? 종류와 관련된 종류와 관련된 무언가가 유형과 관련이 있습니까 (그것이 무엇인지는 모르겠지만).


좋아, 나는 GHC이 종류의 계층 구조를 가지고 있으며, 그`# '은 언 박싱 종류의 특별한 종류 이니까 이해한다. 모두 좋고 좋지만 왜이 오류가 나타 납니까? 어쩌면 박스가없는 타입이 genercis에서 잘 작동하지 않을 수 있습니까?

컴파일러가 수행하는 최적화가 아닌 박스 화되지 않은 유형을 고려할 것이기 때문에 이것이 나에게 아직 의미가 있는지 확신 할 수 없습니다. 또한 데이터 인스턴스가 존재하는 경우 데이터 구조에 포함될 수있는 모든 유형이 있어야한다고 생각했습니다.

추가 조사시 나는 Names이 문제가 될 것이라고 생각합니다. dataToExpQ를 우회하는 방법이 있습니까? 어쨌든 그 논쟁을 어떻게 사용합니까?

+5

'# '은 박스 처리되지 않은 유형입니다. http://stackoverflow.com/a/3034295/700253 – Vitus

+0

힌트를 주셔서 감사합니다. 그래서 : 문제를 해결하는 방법 :-)? – scravy

답변

4

맞아요, 문제를 일으키는 이름입니다. 더 구체적으로, 문제는 일부 필드에서 NameFlavour 데이터 형식의 상자가없는 정수가 있다는 것입니다.

Data NameFlavor 인스턴스에 빨간색 플래그를 발생시키는 대용 참고가 있습니다. 소스를 클릭하면 gfoldl 정의가 본질적으로 정수와 같은 박스 화되지 않은 정수를 처리한다는 것을 알 수 있습니다. (실제로 다른 선택 사항은 많지 않습니다 ...) 이것은 DataTexpQ (사기성 Data NameFlavour 인스턴스에 속았던)가 NameU가 실제로 예상 할 때 NameU를 (Int :: *)에 적용하는 Exp 용어를 작성하기 때문에 궁극적으로 오류가 발생합니다 (unboxed) (Int # :: #).

그래서 문제는 NameFlavour의 Data 인스턴스가 dataToExpQ에 의해 가정 된 불변 조건을 거부한다는 것입니다. 그러나 걱정하지 마라! 이 시나리오는 dataToExpQ가 인수를 취하는 이유에 따라 정면으로 분류됩니다. 인수를 사용하면 문제가있는 유형의 특수 처리를 제공 할 수 있습니다. 아래에서 필자는 박스 화되지 않은 정수 필드가있는 NameFlavour 생성자를 올바르게 나타 내기 위해이 작업을 수행합니다.

거기에 대한 해결책이있을 수 있지만, 나는 그들에 대해 알지 못한다. 그래서 나는 다음을 겹쳐 쓴다. TH 스테이징 제한으로 인해 별도의 모듈이 필요합니다.

{-# LANGUAGE TemplateHaskell #-} 
{-# LANGUAGE MagicHash #-} 

module Stage0 where 

import Language.Haskell.TH 
import Language.Haskell.TH.Syntax 

import GHC.Types (Int(I#)) 
import GHC.Prim (Int#) 

unboxed :: Int# -> Q Exp 
unboxed i = litE $ intPrimL $ toInteger $ I# i -- TH does support unboxed literals 

nameFlavorToQExp :: NameFlavour -> Maybe (Q Exp) 
nameFlavorToQExp n = case n of 
    NameU i -> Just [| NameU $(unboxed i) |] 
    NameL i -> Just [| NameL $(unboxed i) |] 
    _ -> Nothing 

다음 나를 위해 컴파일됩니다.

{-# LANGUAGE TemplateHaskell #-} 

import Language.Haskell.TH 
import Language.Haskell.TH.Quote 

import Generics.SYB 
import Stage0 

info :: Info 
info = $(reify ''Show >>= dataToExpQ (mkQ Nothing nameFlavorToQExp)) 

주의 프로그래머는 우리가 여기에 대해 거꾸로 절곡있는 언 박싱 된 정수는 GHC는 내부적으로 사용을 "순 방문자를"해당합니다. 반드시 직렬화 될 것으로 예상되는 것은 아닙니다. 결과 Info 값을 어떻게 사용 하느냐에 따라 폭발의 원인이 될 수 있습니다.

또한 Show를 구체화 할 때 범위에있는 Show의 모든 인스턴스를 나타냅니다.

  • 꽤 많은 구문 용어가 생성됩니다.

  • the documentation과 같이 이러한 인스턴스에는 메소드 정의가 포함되지 않습니다.

HTH.