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

时间:2015-10-20 20:08:32

标签: haskell recursion

如果我有一个已知列表A :: [Int],并希望获得一个新列表B = newList AnewList定义如下:

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之外,我还想知道0, 1分别有多少A

但是,由于递归生成B时,它已经检查了a== (0 or 1)中每个元素是否A,因此再次检查它是一种冗余。

是否可以获得B,但同时只需检查0, 1 A中有多少private void button1_Click(object sender, EventArgs e) { var fileDialog1 = new OpenFileDialog { InitialDirectory = "c:\\", RestoreDirectory = true }; if (fileDialog1.ShowDialog() == DialogResult.OK) { System.Diagnostics.Process.Start(fileDialog1.FileName); } }

1 个答案:

答案 0 :(得分:4)

这不是您正在寻找的答案,但您的功能背后有一个很好的抽象结构,所以我会留在这里:

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 monad处理幺半群,traverse映射一个带有效函数的列表并执行所有效果。

此:

f = (+ 1)
g = (+ 2)
h = (+ 3)

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

打印([1,3,5,6,1,1,1,7,3],(4,2)) - 四个零和两个。