的最新(2.8.0.0)定义Dec
具有以下实例构造函数:
InstanceD Cxt Type [Dec]
似乎只能实例化一种类型。有没有办法解决这个问题?
的最新(2.8.0.0)定义Dec
具有以下实例构造函数:
InstanceD Cxt Type [Dec]
似乎只能实例化一种类型。有没有办法解决这个问题?
是的,支持多参数类型类。
有点令人困惑的是,该Type
参数指的是整个实例 head,尽管它不是真正的类型,但它在语法上看起来很像一个类型,该类型Type
被重用于此目的。
因此,如果要生成多参数instance Foo Int Bool
,则需要使用“类型” Foo Int Bool
,例如这样构造:
(ConT (mkName "Foo") `AppT` ConT (mkName "Int")) `AppT` ConT (mkName "Bool")
这是一个完整的例子:
{-# LANGUAGE MultiParamTypeClasses, TemplateHaskell #-}
import Language.Haskell.TH
class Foo a b where
foo :: (a, b)
$(return [InstanceD [] (((ConT (mkName "Foo")) `AppT` ConT (mkName "Int")) `AppT` ConT (mkName "Bool"))
[ValD (VarP (mkName "foo"))
(NormalB (TupE [LitE (IntegerL 42), ConE (mkName "False")])) []]])
main = print (foo :: (Int, Bool))
回答这个问题和类似问题的一个简单方法是使用runQ
拼接定义。例如在 ghci 中:
$ ghci
GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help
Prelude> :set -XTemplateHaskell
Prelude> :set -XMultiParamTypeClasses
Prelude> import Language.Haskell.TH
Prelude Language.Haskell.TH> class Class a b where
Prelude Language.Haskell.TH> runQ [d| instance Class Int Bool where |]
[InstanceD [] (AppT (AppT (ConT :Interactive.Class) (ConT GHC.Types.Int)) (ConT GHC.Types.Bool)) []]
这显示了所需的确切形式,替换Class
为您正在使用的任何类。