在Haskell中同时执行递归和计数

在Haskell中同时执行递归和计数,haskell,recursion,Haskell,Recursion,如果我有一个已知的列表a::[Int],并且想要得到一个新的列表B=newList a,其中newList的定义如下: newList :: [Int] -> [Int] newList [] = [] newList (a:as) | a==0 = f(a) : newList (as) | a==1 = g(a) : newList (as) | otherwise = h(a) : newList (as

如果我有一个已知的列表a::[Int],并且想要得到一个新的列表B=newList a,其中newList的定义如下:

newList :: [Int] -> [Int]
newList [] = []
newList (a:as) | a==0      = f(a) : newList (as)
               | a==1      = g(a) : newList (as)
               | otherwise = h(a) : newList (as)
其中f,g,h::Int->Int是不重要的函数

除了B之外,我还想知道A中分别有多少个0和1

但是当递归地生成B时,它已经检查了a中每个元素的a==0还是1,所以再次单独检查它是一种冗余


是否可以得到B,但同时只检查一次,就可以得到A中有多少0,1?

这不是您要寻找的答案,但函数背后有一个很好的抽象结构,因此我将其留在这里:

import Data.Monoid
import Data.Functor
import Data.Traversable
import Control.Arrow
import Control.Monad.Trans.Writer

wr :: Int -> Writer (Sum Int, Sum Int) Int
wr 0 = tell (Sum 1, Sum 0) $> f 0
wr 1 = tell (Sum 0, Sum 1) $> g 1
wr n = return $ h n

collect :: [Int] -> ([Int], (Int, Int))
collect = second (getSum *** getSum) . runWriter . traverse wr
求和是一个幺半群,双求和是一个幺半群,Writer幺半群处理幺半群,使用有效函数遍历映射列表并执行所有效果

这:


打印[1,3,5,6,1,1,1,1,7,3]、4,2-四个0和两个1。

首先,您可以在这里用值f0交换fa,用值g1交换ga-然后是的,这是可能的,例如,您可以使用foldr来完成-也许您想在破坏它之前先看看它?提示:这个想法是将列表折叠成一个元组na,nb,xs,其中na是被视为的数量,nb与bs相同,xs是您在这里使用map h所做的映射列表首先查找使用foldr表示map的方法-附加提示:use:and[];mapAccumR也可以提供帮助,因为它将折叠与贴图结合起来。@chi,为什么不使用mapAccumL?@user3237465,因为上面看起来像是foldr样式的递归。
f = (+ 1)
g = (+ 2)
h = (+ 3)

main = print $ collect [0, 1, 2, 3, 0, 0, 0, 4, 1]