Как я могу сгруппировать один и тот же тип в нескольких местах с помощью Template Haskell?

Я определяю экземпляры классов из векторного пространства для типов OpenGL , и, чтобы сэкономить свои печатные мышцы, я хочу использовать шаблон Haskell, чтобы написать для меня кучу экземпляров.

Я начал с малого с определения функции для получения экземпляров для 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 в оксфордские скобки. . Теперь функция для получения экземпляров VectorSpace :

deriveScalarVectorSpace ts = concat <$> forM (map conT ts) (\t -> [d|    
    instance VectorSpace $t where type Scalar $t = $t; (*^) = (*)
  |])

Но этот barfs:

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.

11
задан acfoltzer 7 December 2011 в 05:18
поделиться