现在我一般都知道如何使用foldr,我通常会考虑使用递归函数,例如,当我看到时,对我来说:
sum xs = foldr (+) 0 xs
我的想法是:
sum [] = 0
sum (x:xs) = x + sum xs
据我所知,这基本上就是foldr的意思。
现在,我有这段代码:
printLine :: [Int] -> String
printLine [] = "+"
printLine (x:xs) = '+' : replicate x '-' ++ printLine xs
它的作用是,例如[5,4],然后打印“+ ----- + ---- +”。现在,我真的想知道如何使用foldr编写这个。它遵循递归函数的一般概念,所以我认为它应该是可行的。我尝试过使用lambda函数并翻转复制恶作剧,但似乎没有任何效果。有什么提示吗?
答案 0 :(得分:3)
试试这个:
withFoldr :: [Int] -> String
withFoldr xs = foldr go "+" xs
where go x b = ('+' : replicate x '-') ++ b
一般来说,当你有一个表达式
f as = foldr go a bs
然后a
等于f []
。 go
函数具有签名go :: a -> b -> b
并且对应于printLine
的递归情况:
-- match up with go :: a -> b -> b
printLine (x:xs) = '+' : replicate x '-' ++ printLine xs
在此,我们将a
与x
和b
与printLine xs
联系起来,以便go
成为:
go a b = ('+' : replicate a '-') ++ b
答案 1 :(得分:3)
另一种可能性:
$scope.categories
答案 2 :(得分:2)
你可以用很少的改变来编写它的一个版本:
printL = foldr alg "+" where
alg x xs = '+' : replicate x '-' ++ xs
将xs
视为已经适当处理的组件可能会有所帮助;您处理x
(通过将'+'
添加到-
复制x
次),然后将“已处理”xs
附加到该页面。
答案 3 :(得分:2)
我猜你想要一个无点表示作为学术练习传递给foldr
。以下是我将如何处理这个问题。
首先,我会使用lambdas编写表达式:
Prelude> let pp = foldr (\x -> \s -> s ++ (replicate x '-') ++ "+") "+"
Prelude> pp [4,5]
"+-----+----+"
现在,我会努力让表达式一次点一个参数。首先,取消s
:
Prelude> let pp = foldr (\x -> flip (++) ((replicate x '-') ++ "+")) "+"
Prelude> pp [4,5]
"+-----+----+"
现在,x
,首先将其移动为内部函数的最后一个参数:
Prelude> let pp = foldr (\x -> flip (++) ((flip replicate '-' x) ++ "+")) "+"
Prelude> pp [4,5]
"+-----+-
然后又迈出了一步:
Prelude> let pp = foldr (\x -> flip (++) (flip (++) "+" (flip replicate '-' x))) "+"
Prelude> pp [4,5]
"+-----+----+"
现在这有点失控,所以这是下一步的简写:
Prelude> let f = flip (++)
Prelude> let g = f "+"
Prelude> let h = flip replicate '-'
Prelude> let pp = foldr (\x -> f (g (h x))) "+"
让最后一点免费很容易!
Prelude> let pp = foldr (f . g . h) "+"
Prelude> pp [4,5]
"+-----+----+"
现在替换f
,g
和h
,您就会得到答案。但是,这应该只是一个学术练习,我不会想象在实际的生产代码中使用这样的东西。
@WillNess建议使用我完全忘记的operator sections (see right section)。它们允许人们在两个地方省略翻转,导致更加令人讨厌的事情:
原件:
Prelude> let pp = foldr ((flip (++)) . (flip (++) "+") . (flip replicate '-')) "+"
更改为:
Prelude> let pp = foldr ((flip (++)) . (++ "+") . (`replicate` '-')) "+"
Prelude> pp [4,5]
"+-----+----+"