gpt4 book ai didi

haskell - 由于 "fold"的功能不足以编写带有缩进的树形 pretty-print ,那么什么是高阶组合器呢?

转载 作者:行者123 更新时间:2023-12-02 16:13:24 25 4
gpt4 key购买 nike

例如,给定以下树数据类型:

data Tree a = Node [Tree a] | Leaf a deriving Show
type Sexp = Tree String

如何使用高阶组合器表达“漂亮”的函数,以正确的缩进打印树?例如:

sexp = 
Node [
Leaf "aaa",
Leaf "bbb",
Node [
Leaf "ccc",
Leaf "ddd",
Node [
Leaf "eee",
Leaf "fff"],
Leaf "ggg",
Leaf "hhh"],
Leaf "jjj",
Leaf "kkk"]
pretty = ????
main = print $ pretty sexp

我希望该程序的结果是:

(aaa 
bbb
(ccc
ddd
(eee
fff)
ggg
hhh)
jjj
kkk)

这是一个不完整的解决方案,使用“折叠”作为组合符,没有实现缩进:

fold f g (Node children) = f (map (fold f g) children)
fold f g (Leaf terminal) = g terminal
pretty = fold (\ x -> "(" ++ (foldr1 ((++) . (++ " ")) x) ++ ")") show
main = putStrLn $ pretty sexp

显然不可能使用fold编写我想要的函数,因为它忘记了树结构。那么,什么是一个合适的高阶组合器,它足够通用,可以让我编写我想要的函数,但不如编写直接递归函数强大?

最佳答案

fold 足够强大;诀窍是我们需要将 r 实例化为当前缩进级别的读取器 monad。

fold :: ([r] -> r) -> (a -> r) -> (Tree a -> r)
fold node leaf (Node children) = node (map (fold node leaf) children)
fold node leaf (Leaf terminal) = leaf terminal

pretty :: forall a . Show a => Tree a -> String
pretty tree = fold node leaf tree 0 where

node :: [Int -> String] -> Int -> String
node children level =
let childLines = map ($ level + 1) children
in unlines ([indent level "Node ["] ++ childLines ++ [indent level "]"])

leaf :: a -> Int -> String
leaf a level = indent level (show a)

indent :: Int -> String -> String -- two space indentation
indent n s = replicate (2 * n) ' ' ++ s

请注意,我向 fold 的调用传递了一个额外的参数。这是缩进的初始状态,它之所以有效,是因为通过 r 的这种特化,fold 返回一个函数。

关于haskell - 由于 "fold"的功能不足以编写带有缩进的树形 pretty-print ,那么什么是高阶组合器呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28533221/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com