我想构建一个抽象来使用不同的模板引擎:
class Template a where
process :: a -> Model -> IO String
class TemplateEngine a where
buildTemplate :: (Template b) => a -> BufferedReader -> IO b
我的第一次尝试是调整Groovy模板,以便实现所需的数据类型:
data GroovyWritable = mutable native groovy.lang.Writable where
native writeTo :: GroovyWritable -> Writer -> IO Writer
throws IOException
data GroovyTemplate = mutable native groovy.text.Template where
native make :: GroovyTemplate -> HashMap -> IO GroovyWritable
data GroovyEngine = mutable native groovy.text.markup.MarkupTemplateEngine where
native new :: () -> IO GroovyEngine
native createTemplate :: GroovyEngine -> BufferedReader -> IO GroovyTemplate
throws ClassNotFoundException, IOException
然后我做了相应的实例:
instance Template GroovyTemplate where
process template model = do -- model is not used at the moment
config <- HashMap.new ()
writable <- GroovyTemplate.make template config
stWriter <- StringWriter.new ()
writer <- writable.writeTo stWriter
writer.toString
instance TemplateEngine GroovyEngine where
buildTemplate engine reader = GroovyEngine.createTemplate engine reader
但编译器抱怨:
...
type `GroovyTemplate` is not as polymorphic as suggested
in the annotation where just `α` is announced.
...
type error in expression createTemplate engine reader
type is : IO GroovyTemplate
expected: IO α
有什么想法吗?我应该使用不同的策略吗? 感谢
更新:
为了解释我正在尝试做什么,我正在添加一个函数,表示从给定模板引擎构建模板的一般方法。
让我说我了解Frege需要更精确地了解类型,TemplateEngine
的实例和包含模板文件内容的BufferedReader
,执行buildTemplate
函数一个给定的引擎应该给我一个Template
的实例。这里的这个功能正在编译,完全没有警告。
execute :: (TemplateEngine a, Template b) => a -> BufferedReader -> IO b
execute engine reader = buildTemplate engine reader
我很困惑,为什么编译器不抱怨这里?它不应该像以前那样抱怨吗?
更新II(工作解决方案):
按照Ingo的推荐,我完成了设计背后的理由,并找到了可行的解决方案。
一开始我认为让TemplateEngine
类型类以相同的方式创建模板引擎实例会很棒。
但最重要的部分是有一个公共类型类来处理模板,其中包括可以缓存模板。所以最重要的是,只要生成的模板是Template
的实例,我就不关心模板的来源。
遵循这个前提,我可以有一个共同的功能来处理模板并获得生成的html / json / xml ......等。
execute :: (Template a) => a -> Model -> IO String
execute tpl model = tpl.process model
当然production-ready
签名应该是这样的:
execute :: (Template a) => a -> Model -> Either TemplateException String
答案 0 :(得分:1)
我不完全确定您将要做什么,但就目前而言,GroovyEngine.createTemplate
方法不能用于将GroovyEngine
实例化为TemplateEngine
。由于buildTemplate
操作承诺返回调用者想要的任何Template
,只要将Template
实例作为参数传递。
现在,第一个问题是本机方法无法处理类型类约束。我们可以通过使用实际使用Template
约束的frege函数包装对本机方法的调用来解决此问题。但话说再说一遍,目前还不清楚如何实际创建一个合适的值,因为Template
类并没有提供相应的操作。并且GroovyEngine.createTemplate
仍然符合条件,因为它始终会创建一个特定的模板,而不是依赖于约束的模板。