抽象出我调用的函数

时间:2019-02-12 09:40:11

标签: haskell

我有一个函数,可以创建彩色的语法输出

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的多余参数。

2 个答案:

答案 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

如果可能,您可能更喜欢

  • 您希望类型系统确保您不会混淆XML和ANSI字符串
  • 您具有多个格式化功能,这可能会使显式词典传递变得笨拙。 (我认为这与您有关,因为您说的是“ argument s ”。)

请注意,返回类型多态通常会迫使您使用更多类型注释来告诉编译器您的意思。 TypeApplications扩展名可以帮助您:

> :t printKeyword @XML
printKeyword @XML :: AST -> XML