在Template Haskell splice中规范化类型族实例

时间:2014-09-26 13:24:02

标签: haskell ghc template-haskell type-families data-kinds

我使用genifunctors包为其定义涉及类型系列的类型生成仿函数实例。

第一个模块定义数据类型本身:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
module Temp where

data Record (p :: (*,*))

type family Fst p where Fst (Record '(a,b)) = a
type family Snd p where Snd (Record '(a,b)) = b

data Bar s = Bar {
  field_a :: Fst s,
  field_b :: Snd s
}

newtype Baz a = Baz { getBaz :: Bar (Record '(Maybe a, [a])) }

这与预期一样:

λ> import Temp 
λ> :t Baz $ Bar (Just "a") ["b"] 
Baz $ Bar (Just "a") ["b"] :: Baz [Char]

Functor实例在单独的模块中定义:

{-# LANGUAGE TemplateHaskell #-}
module Temp2 where

import Temp

import Data.Generics.Genifunctors

instance Functor (Baz a) where
  fmap = $(genFmap ''Baz)

并给出了这个错误:

λ> import Temp1
src/Temp2.hs:9:12-24: Exception when trying to run compile-time code: …
  unexpected TyCon: FamilyI (ClosedTypeFamilyD Temp.Fst [PlainTV p_1627394000] (Just StarT) [TySynEqn [AppT (ConT Temp.Record) (AppT (AppT (ConT GHC.Tuple.(,)) (VarT a_1627394001)) (VarT b_1627394002))] (VarT a_1627394001)]) []
Code: genFmap ''Baz
In the splice: $(genFmap ''Baz)

这是因为genifunctors,就像geniplate一样,只能处理 从newtypedata声明中输入构造函数。

这可以通过在递归检查之前规范化类型来解决。

那么,有没有办法在Template Haskell拼接中这样做? (即 在Q monad中?)

0 个答案:

没有答案