- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
Chapter 5 of Real World Haskell在pretty printingJSON的上下文中引入了一个漂亮的打印库,特别是一个抽象的Doc
:
我们的prettify模块将使用一个抽象类型,我们将调用doc,而不是直接呈现为字符串。通过将通用渲染库建立在抽象类型上,我们可以选择灵活高效的实现方式。如果我们决定更改底层代码,我们的用户将无法分辨。
然而(正如几位评论员在这本书上写的那样),从这一章中很难理解为什么需要Doc
,或者它到底是如何解决这个问题的。具体地说,在一章的重点是模块的背景下,很难理解
如果我们决定更改底层代码,我们的用户将无法分辨。
这本身可以通过简单地导出一个漂亮的打印函数来实现,而不导出与实现相关的任何内容。那么,为什么需要Doc
呢?它如何解决这个问题呢?
最佳答案
我花了很多时间阅读了第5章以及[Hughes 95]和[Wadler 98]后,自己回答了这个问题,原因如下:
本章同时讨论了许多不同的点(例如,json、漂亮的打印、hex格式、haskell模块、签名需求等)。
本章出乎意料地在非常高级和低级的问题之间移动,例如,泛型漂亮打印和转义JSON字符串;有点奇怪的是,转义的讨论是在从JSON特定打印过渡到泛型漂亮打印之后开始的。
IIUC,[Wadler 98]提供了一个非常优雅的框架和解决方案,但是它在这里的具体用途可以简化为大约20 lines of very straightforward code(参见full version here)。
一个漂亮的打印库和Doc
许多文档和数据结构都是(多路)树状的:
json,YANG和基本上任何具有层次结构的文档
许多purely functional data structures
因此,从树状数据的实际源中分离出漂亮的树打印是有意义的。这个分解出来的库将只包含从树状数据构造一些抽象的Doc
的方法,并很好地打印这个Doc
因此,重点是同时为几种类型的源提供服务。
为了简化问题,让我们关注一个特别简单的来源:
data Tree = Tree String [Tree]
deriving (Eq, Show)
tree =
Tree "a" [
Tree "b" [
Tree "c" []],
Tree "d" [
Tree "e" [],
Tree "f" [],
Tree "g" [],
Tree "h" []
],
Tree "i" []
]
tree
,如果给定长度30,则最漂亮的输出定义为
a[[c] d[e, f, g, h] i]
a[
b[c]
d[e, f, g, h]
i
]
a[
b[c]
d[
e,
f,
g,
h
]
i
]
Doc
的实现
data Doc =
Text String Int
| Nest Int String [Doc] String Int
deriving (Eq, Show)
Text
类型只包含
String
的内容
Nest
类型包含
Int
。
String
表示开始元素
[Doc]
表示子元素
String
表示关闭元素
Int
。
Doc
的长度,如果折叠,使用这个:
getDocFoldedLength :: Doc -> Int
getDocFoldedLength (Text s) = length s
getDocFoldedLength (Nest _ _ _ _ l) = l
Nest
,我们使用以下命令:
nest :: Int -> String -> [Doc] -> String -> Doc
nest indent open chs close =
Nest indent open chs close (length open + length chs - 1 + sum (map getDocFoldedLength chs) + length close)
Doc
的折叠版本长度很容易:
getDocFoldedLength :: Doc -> Int
getDocFoldedLength (Text s) = length s
getDocFoldedLength (Nest _ _ _ _ l) = l
Doc
,我们还需要其内容的折叠版本:
getDocFoldedString :: Doc -> String
getDocFoldedString (Nest _ open cs close _) = open ++ intercalate " " (map getDocFoldedString cs) ++ close
getDocFoldedString (Text s) = s
Doc
可以这样做:
showTree :: Tree -> Doc
showTree (Tree s ts) = if null chs then Text s else nest (1 + length s) (s ++ "[") chs "]" where
chs = intercalateDocs "," $ map showTree ts
intercalateDocs
是一个实用函数,在非-
Nest
Docs
之间插入逗号:
intercalateDocs :: String -> [Doc] -> [Doc]
intercalateDocs _ l | length l < 2 = l
intercalateDocs delim (hd:tl) = case hd of
(Text s) -> (Text (s ++ delim)):intercalateDocs delim tl
otherwise -> hd:intercalateDocs delim tl
tree
给出
Nest 2 "a[" [Nest 2 "b[" [Text "c"] "]" 4,Nest 2 "d[" [Text "e,",Text "f,",Text "g,",Text "h"] "]" 13,Text "i"] "]" 23
showTree tree
函数,决定折叠哪些嵌套元素。由于每个
pretty
都给出了折叠版a
getDocElement
的长度,因此我们可以有效地决定是否折叠:
pretty :: Int -> Doc -> String
pretty w doc = pretty' 0 w doc where
pretty' i _ (Text s) = replicate i ' ' ++ s
pretty' i w (Nest j open cs close l) | i + j + l <= w =
replicate i ' ' ++ open ++ intercalate " " (map getDocFoldedString cs) ++ close
pretty' i w (Nest j open cs close l) =
replicate i ' ' ++ open ++ "\n" ++ intercalate "\n" (map (pretty' (i + j) w) cs) ++ "\n" ++ replicate i ' ' ++ close
Doc
将
pretty' i w doc
转换为一个漂亮的形式,假设当前缩进
doc
,宽度
i
明确地,
w
转换为字符串
Text
;如果不合适,它会递归地在子对象上调用自己。
Nest
的代数数据类型还包括一个“水平连接”,它根据文档(以及子文档)是否折叠而生成一系列文档。仔细的搜索不会生成所有可能的文档(其数量是指数型的),而是放弃生成大量布局,这些布局不可能是最优解决方案的一部分这里的解决方案通过缓存每个节点内的折叠长度来实现相同的复杂性,这更简单。
关于algorithm - Doc在现实世界中的目的和工作Haskell,第5章,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43916704/
我在一本书(Interview Question)中读到这个问题,想在这里详细讨论这个问题。请点亮它。 问题如下:- 隐私和匿名化 马萨诸塞州集团保险委员会早在 1990 年代中期就有一个绝妙的主意
我最近接受了一次面试,面试官给了我一些伪代码并提出了相关问题。不幸的是,由于准备不足,我无法回答他的问题。由于时间关系,我无法向他请教该问题的解决方案。如果有人可以指导我并帮助我理解问题,以便我可以改
这是我的代码 public int getDist(Node root, int value) { if (root == null && value !=0) return
就效率而言,Strassen 算法应该停止递归并应用乘法的最佳交叉点是多少? 我知道这与具体的实现和硬件密切相关,但对于一般情况应该有某种指南或某人的一些实验结果。 在网上搜索了一下,问了一些他们认为
我想学习一些关于分布式算法的知识,所以我正在寻找任何书籍推荐。我对理论书籍更感兴趣,因为实现只是个人喜好问题(我可能会使用 erlang(或 c#))。但另一方面,我不想对算法进行原始的数学分析。只是
我想知道你们中有多少人实现了计算机科学的“ classical algorithms ”,例如 Dijkstra's algorithm或现实世界中的数据结构(例如二叉搜索树),而不是学术项目? 当有
我正在解决旧编程竞赛中的一些示例问题。在这个问题中,我们得到了我们有多少调酒师以及他们知道哪些食谱的信息。制作每杯鸡尾酒需要 1 分钟,我们需要使用所有调酒师计算是否可以在 5 分钟内完成订单。 解决
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
我开始学习 Nodejs,但我被困在中间的某个地方。我从 npm 安装了一个新库,它是 express -jwt ,它在运行后显示某种错误。附上代码和错误日志,请帮助我! const jwt = re
我有一个证书,其中签名算法显示“sha256rsa”,但指纹算法显示“sha1”。我的证书 SHA1/SHA2 的标识是什么? 谢谢! 最佳答案 TL;TR:签名和指纹是完全不同的东西。对于证书的强度
我目前在我的大学学习数据结构类(class),并且在之前的类(class)中做过一些算法分析,但这是我在之前的类(class)中遇到的最困难的部分。我们现在将在我的数据结构类(class)中学习算法分
有一个由 N 个 1x1 方格组成的区域,并且该区域的所有部分都是相连的(没有任何方格无法到达的方格)。 下面是一些面积的例子。 我想在这个区域中选择一些方块,并且两个相邻的方块不能一起选择(对角接触
我有一些多边形形状的点列表,我想将其包含在我页面上的 Google map 中。 我已经从原始数据中删除了尽可能多的不必要的多边形,现在我剩下大约 12 个,但它们非常详细以至于导致了问题。现在我的文
我目前正在实现 Marching Squares用于计算等高线曲线,我对此处提到的位移位的使用有疑问 Compose the 4 bits at the corners of the cell to
我正在尝试针对给定算法的约束满足问题实现此递归回溯函数: function BACKTRACKING-SEARCH(csp) returns solution/failure return R
是否有包含反函数的库? 作为项目的一部分,我目前正在研究测向算法。我正在使用巴特利特相关性。在 Bartlett 相关性中,我需要将已经是 3 次矩阵乘法(包括 Hermitian 转置)的分子除以作
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 8 年前。 Improve
问题的链接是UVA - 1394 : And There Was One . 朴素的算法是扫描整个数组并在每次迭代中标记第 k 个元素并在最后停止:这需要 O(n^2) 时间。 我搜索了一种替代算法并
COM 中创建 GUID 的函数 (CoCreateGUID) 使用“分散唯一性算法”,但我的问题是,它是什么? 谁能解释一下? 最佳答案 一种生成 ID 的方法,该 ID 具有一定的唯一性保证,而不
在做一个项目时我遇到了这个问题,我将在这个问题的实际领域之外重新措辞(我想我可以谈论烟花的口径和形状,但这会使理解更加复杂).我正在寻找一种(可能是近似的)算法来解决它。 我有 n 个不同大小的容器,
我是一名优秀的程序员,十分优秀!