我做了一些Criterion基准测试,通过在monad堆栈上运行我的代码来估计我失去了多少性能.结果很奇怪,我可能在我的基准测试中偶然发现了一些懒惰的陷阱.
基准测试告诉我,即使不使用,WriterT String IO运行速度也比运行简单快20倍(!).古怪的,如果我栈与和它仅仅是5倍速度较慢.这可能是我的基准测试中的一个错误.我在这做错了什么?IOtellWriterTReaderTContT
{-#LANGUAGE BangPatterns#-}
module Main where
import Criterion.Main
import Control.Monad
import Control.Monad.Writer
import Control.Monad.Reader
import Control.Monad.Cont
process :: Monad m => Int -> m Int
process = foldl (>=>) return (replicate 100000 (\(!x) -> return (x+1)))
test n = process n >> return ()
main = defaultMain [
      bench "Plain"  t0
     ,bench "Writer" t1
     ,bench "Reader" t2
     ,bench "Cont"   t3
     ,bench "RWC"    t4
    ]
t0 = test 1 :: …对于那些有可疑头脑的人来说,这不是家庭作业,只是好奇.
给定一个有限的字母表,是否有可能构建一个由反向词汇顺序的字母表组成的无限长单词列表?
即给出字母表 "ab"
是否可以构建列表:
["aaaaaa...", "baaaaa...", "abaaaa...", "bbaaaa...", "aabaaa...", ...]
where ...表示扩展到无限长度的列表(和列表列表).
一个天真的尝试是:
counters alphabet = [c:ounter | ounter <- counters alphabet, c <- alphabet]
但这不起作用,因为它是递归的.
当然,对于工作版本,如果您尝试打印结果,则只会看到第一个元素被打印为字母表中第一个元素的无限列表.但是,您应该能够这样做:
mapM_ (print . take 2) . take 4 . counters $ "ab"
并看到输出:
aa
ba
ab
bb