Haskell 漂亮的打印JavaScript对象

Haskell 漂亮的打印JavaScript对象,haskell,pretty-print,Haskell,Pretty Print,我选择将这个问题集中在JSON对象和()上,因为它们使MVCE变得容易,但我的问题实际上并不是简单地打印JSON对象,我可以灵活地选择使用哪个打印库 考虑以下简化的JavaScript对象数据类型: data Object = Object [(String, Object)] | String String 我如何定义一个漂亮的打印函数,以通常的方式将其输出包装到多行?我的意思是:漂亮的打印输出应尽可能适合一行。如果不可能,我希望最外层的对象开始在内部对象之前添加换

我选择将这个问题集中在JSON对象和()上,因为它们使MVCE变得容易,但我的问题实际上并不是简单地打印JSON对象,我可以灵活地选择使用哪个打印库


考虑以下简化的JavaScript对象数据类型:

data Object = Object [(String, Object)]
            | String String
我如何定义一个漂亮的打印函数,以通常的方式将其输出包装到多行?我的意思是:漂亮的打印输出应尽可能适合一行。如果不可能,我希望最外层的对象开始在内部对象之前添加换行符

下面是一个尝试,使用:

我希望最后的输出是

{
  key5: { key1: "val1" },
  key6: {
    key2: "val2",
    looooooooooong key3: "loooooooooooong val3",
    key4: "val4"
  },
  key7: "val7"
}
我正在寻找一种与Haskell中现有的漂亮打印库(实际上,我打印的不仅仅是JSON的一个子集)相匹配的解决方案


我不是在寻找一种定义
prettyObject::Object->String
的解决方案-这种方法的全部要点是
Doc
的呈现取决于它在漂亮打印的大图中的位置。

您正在使用的漂亮打印库已经可以做到这一点;(你刚刚告诉它做一件不同的事情!)一般来说,这个漂亮的打印机家族(WL)很好地处理了这个问题

注意
接头的位置

prettyObject (Object fields) = Union <one line> <many line>
您需要一个函数来实现所需的键值对逻辑:

indent' k x = flatAlt (indent k x) (flatten x) 
prettyKVPair (k,v) = indent' 2 $ text k <> ":" <+> pretty v
注:没有明确的
联合
,而是
sep=group。vsep
组=\x->联合(展平x)x
。现在,您有了一个联合,它对应于关于文本展开位置的逻辑选择

结果是:

>pretty o1
{ key1: "val1" }
>pretty o2
{
  key2: "val2",
  looooooooooong key3: "loooooooooooong val3",
  key4: "val4"
}
>pretty o3
{
  key5: "val5",
  key6: {
    key2: "val2",
    looooooooooong key3: "loooooooooooong val3",
    key4: "val4"
  },
  key7: "val7"
}

针对评论中的问题,提供平面替代方案的方法当然是使用
flatAlt
!这里唯一的问题是您希望对列表中的单个元素(最后一个)执行此操作,但这是列表的问题,而不是
Doc
。您可以随意使用
数据。序列
或任何其他可遍历的
标点
等大多数“类似列表”的功能都可以使用这些功能,如果这是一项您非常需要的操作的话

flattenedOf a b = flatAlt a (flatten b) # useful combinator

trailingSep _ [] = [] 
trailingSep s xs = as ++ [ (a <> s) `flattenedOf` a ]
  where as = init xs; a = last xs 

...
prettyObject (Object fields) = <unchanged> where 
  fields' = trailingSep "," $ <unchanged>
flattedof a b=flatAlt a(flatte b)#有用的组合器
trailingSep[]=[]
trailingSep s xs=as++[(as)`flattedof`a]
其中as=init xs;a=最后一个X
...
prettyObject(对象字段)=其中
字段“=trailingSep”,“$

非常感谢!这真是一个惊人的答案/解释。
indent' k x = flatAlt (indent k x) (flatten x) 
prettyKVPair (k,v) = indent' 2 $ text k <> ":" <+> pretty v
prettyObject :: Object -> Doc a 
prettyObject (Object fields) = sep $ "{" : fields' ++ [ "}" ] where 
  fields' = punctuate "," $ map prettyKVPair fields
...
>pretty o1
{ key1: "val1" }
>pretty o2
{
  key2: "val2",
  looooooooooong key3: "loooooooooooong val3",
  key4: "val4"
}
>pretty o3
{
  key5: "val5",
  key6: {
    key2: "val2",
    looooooooooong key3: "loooooooooooong val3",
    key4: "val4"
  },
  key7: "val7"
}
flattenedOf a b = flatAlt a (flatten b) # useful combinator

trailingSep _ [] = [] 
trailingSep s xs = as ++ [ (a <> s) `flattenedOf` a ]
  where as = init xs; a = last xs 

...
prettyObject (Object fields) = <unchanged> where 
  fields' = trailingSep "," $ <unchanged>