5

Какого черта здесь происходит:не могли бы соответствовать рода `* 'против' #'

"Couldn't match kind `*' against `#'" 

Я пытался следующее GHCi с помощью TemplateHaskell (ghci -XTemplateHaskell)

$(reify ''Show >>= dataToExpQ (const Nothing)) 

I надеялся получить Exp из этого (у которого есть экземпляр Show). Я делаю это, чтобы вставить информацию о типах haskell в приложение, чтобы она была доступна как фактические данные, а не как строка.

Моя цель заключается в следующем:

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

Я действительно не понимаю, что сообщение об ошибке, что «#» в любом случае? Если есть #, есть ли также # -> # или * -> #? Это что-то, что относится к видам вроде видов, относящихся к типам (хотя я бы не знал, что это может быть)?


Хорошо, так что я теперь понимаю, что GHC имеет иерархию видов и что `#» это особый вид Unboxed типов. Все хорошо и хорошо, но почему эта ошибка появляется? Возможно, распакованные типы не хорошо работают с genercis?

Я не совсем уверен, что это имеет смысл для меня еще, так как я считаю, что unboxed types является оптимизацией, выполняемой компилятором. Я также подумал, что если экземпляр Data существует, он должен быть там для всех типов, которые могут быть включены в структуру данных.

При дальнейших расследованиях я считаю, что Names представляет проблему, есть ли способ обойти их в dataToExpQ? Как использовать этот аргумент в любом случае?

+5

'#' - это тип распакованных типов, см. Http://stackoverflow.com/a/3034295/700253 – Vitus

+0

спасибо за подсказку. так: как решить проблему :-)? – scravy

ответ

4

Вы правы, именно Имена вызывают проблему. Более конкретно, проблема заключается в том, что тип данных NameFlavour имеет незапакованные целые числа в некоторых своих полях.

В примере с именем NameFlavor есть надпись «Пикша», в которой появляются несколько красных флагов. И если вы перейдете к исходному коду, вы увидите, что определение gfoldl по существу относится к целым числам unboxed, таким как целые числа. (У вас действительно не так много другого выбора ...) Это в конечном счете вызывает ошибку, которую вы видите, потому что dataToExpQ, обманутый обманчивым экземпляром Data NameFlavour, создает термин Exp, который применяет NameU к (Int :: *), когда NameU действительно ожидает (unboxed) (Int # :: #).

Таким образом, проблема в том, что экземпляр Data для NameFlavour не подчиняется инварианту, принятому dataToExpQ. Но не волноваться! Этот сценарий подпадает под то, что dataToExpQ принимает аргумент: аргумент позволяет нам обеспечить особую обработку проблемных типов. Ниже, я делаю это, чтобы правильно воссоздать конструкторы NameFlavour, которые имеют unboxed целочисленные поля.

Там могут быть решения для этого, но я не знаю о них, поэтому я свернул следующее. Он требует отдельного модуля из-за ограничения постановки 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)) 

CAVEAT программисту Unboxed целые числа мы более гибки назад для здесь соответствуют «уникумов», что GHC использует внутренне. Они не обязательно должны быть сериализованы. В зависимости от того, как вы используете полученное значение Info, это может вызвать взрывы.

Также обратите внимание, что при обновлении Show, вы также обновляете каждый экземпляр Show, который находится в области видимости.

  • Их много - это создает довольно большой синтаксический термин.

  • Как указано в the documentation, эти экземпляры не включают определения метода.

HTH.