OpenGLタイプのベクトル空間からクラスのインスタンスを定義しています。タイピングの筋肉を節約するために、TemplateHaskellを使用して一連のインスタンスを作成したいと思います。
AdditiveGroup
私は、次のインスタンスを派生させる関数を定義することから始めました。
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module Data.VectorSpace.OpenGL.TH where
import Control.Applicative
import Control.Monad
import Data.AdditiveGroup
import Data.VectorSpace
import Language.Haskell.TH
deriveScalarAdditive ts = concat <$> forM (map conT ts) (\t -> [d|
instance AdditiveGroup $t where zeroV = 0; (^+^) = (+); negateV = negate
|])
$t
これは問題なく機能しますが、オックスフォードブラケットに1回だけ接続していることに注意してください。VectorSpace
ここで、インスタンスを派生させる関数は次のとおりです。
deriveScalarVectorSpace ts = concat <$> forM (map conT ts) (\t -> [d|
instance VectorSpace $t where type Scalar $t = $t; (*^) = (*)
|])
しかし、このバーフ:
Type indexes must match class instance head
Found `t_tt' but expected `t_ts'
In the associated type instance for `Scalar'
In the instance declaration for `VectorSpace $t'
In the Template Haskell quotation
[d| instance VectorSpace $t where
type instance Scalar $t = $t
{ *^ = (*) } |]
t_ts
との違いはt_tt
、THがスプライスするたびに新しい一意の名前を作成していることを示しています$t
。もちろん、これらのタイプが同じ場合にのみ定義が機能します。
オックスフォードブラケットで必要な動作を実現する方法はありますか、それとも古き良きレキシカルスコープとLanguage.Haskell.TH
コンビネータにフォールバックする必要がありますか?これはおそらくCPPの方が簡単だと思いますが、この機会にTHを学びたいと思います。