我有一个函数,可以创建彩色的语法输出
requestById(id)
函数 printKeyword :: AST -> String
printKeyword a = keywordColor (show a)
对于不同的输出应该有所不同。例如,当生成xml keywordColor时,可能看起来像这样
keywordColor
当打印到ANSI终端时,它应该看起来像这样
keywordColor :: String -> String
keywordColor k = "<keyword>" ++ k ++ "</keyword>"
我可以用什么方式编写 keywordColor :: String -> String
keywordColor k = "\ESC[28;2;24;255;128m" ++ k ++ "\ESC[0m"
来抽象出printKeyword
,以便可以将keywordColor
的相同实现与不同的输出配合使用?我可以使用monad还是monadtransformers?如果是这样,那将如何工作?
printKeyword
的实现应保持尽可能简单,因此我想到的是monads,因此不必“手动”携带printKeyword
的多余参数。
答案 0 :(得分:2)
您可以将printKeyword :: (String -> String) -> AST -> String
printKeyword keyWordColor a = keywordColor (show a)
xmlKeywordColor :: String -> String
xmlKeywordColor k = "<keyword>" ++ k ++ "</keyword>"
termKeywordColor :: String -> String
termKeywordColor k = "\ESC[28;2;24;255;128m" ++ k ++ "\ESC[0m"
作为参数传递给{{1}}:
{{1}}
答案 1 :(得分:1)
printKeyword
的实现应保持尽可能简单,因此我想到的是monads,因此不必“手动”携带printKeyword
的多余参数。
类型类会自动将多余的参数传递给函数。这是Izaak显式词典传递的替代方法,并且还允许您将更多信息编码为类型。为此,必须为每种输出格式添加一种类型
newtype XML = XML String
newtype ANSI = ANSI String
和一个为您管理字典传递的类型类
class Formatted a where
keywordColor :: String -> a
和您类型的实现
instance Formatted XML where
keywordColor k = XML $ "<keyword>" ++ k ++ "</keyword>"
instance Formatted ANSI where
keywordColor k = ANSI $ "\ESC[28;2;24;255;128m" ++ k ++ "\ESC[0m"
最后,将printKeyword
实现为
printKeyword :: Formatted a => AST -> a
printKeyword = keywordColor . show
如果可能,您可能更喜欢
请注意,返回类型多态通常会迫使您使用更多类型注释来告诉编译器您的意思。 TypeApplications
扩展名可以帮助您:
> :t printKeyword @XML
printKeyword @XML :: AST -> XML