8

以下はコンパイルされません。

import Language.Haskell.TH
makeAlpha n = [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]

エラーの意味がまったくわかりません:

Can't derive instances where the instance context mentions
type variables that are not data type parameters
  Offending constraint: Show t_d
When deriving the instance for (Show Alpha)
In the Template Haskell quotation
  [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]
In the expression:
  [d| data Alpha = Alpha $(conT n) deriving (Show, Read) |]

このような派生を行うことは可能ですか?

4

1 に答える 1

7

この問題は、TH クォートがコンパイル時に型チェックされ、スプライスが変数に置き換えられるために発生します。これは、splice を実行する前にさまざまな種類の問題を検出できるため、通常は良い考えですが、場合によっては、コンパイラが有効なコードを生成する splice を誤って拒否する可能性があります。

この場合、これは、コンパイラがこのコードをチェックしようとすることを意味します。

data Alpha = Alpha t deriving (Show, Read)

派生したShowおよびReadインスタンスはShowおよびReadforを使用する必要があるため、これは機能しませんtが、tは の型パラメータではないためAlpha、必要な制約を追加できません。もちろん、このスプライスが実行tされると、具象型に置き換えられるため、制約を必要とせずに適切なインスタンスを使用できます。これは、コンパイラが慎重すぎるケースの 1 つです。

回避策は、クォートを使用せず、代わりにこれらの追加チェックの対象とならない TH コンビネータを使用することです。面倒ですが、うまくいきます:

makeAlpha n = sequence [dataD (cxt []) alpha []
                [normalC alpha [strictType notStrict (conT n)]] [''Show, ''Read]]
  where alpha = mkName "Alpha"

quotes で行われるチェックを緩和することについていくつかの話がありましたが、今のところは対処する必要があります。

于 2011-12-31T18:35:14.527 に答える