爲Dec
最新版本(2.8.0.0)的定義有以下實例構造函數:Can Template Haskell可以生成多參數類型實例嗎?
InstanceD Cxt Type [Dec]
似乎只有一種類型可以被實例化。有沒有辦法解決這個問題?
爲Dec
最新版本(2.8.0.0)的定義有以下實例構造函數:Can Template Haskell可以生成多參數類型實例嗎?
InstanceD Cxt Type [Dec]
似乎只有一種類型可以被實例化。有沒有辦法解決這個問題?
是的,支持多參數類型的類。
有點混亂,的Type
參數指的是整個實例頭,並且,即使它不是一個真正的類型,它看起來像足一個語法該類型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
與任何類,你正在使用。