我使用Store comonad 编写了Conway的生命游戏的简单实现(参见下面的代码).我的问题是,从第五次迭代开始,网格生成明显变慢.我的问题与我使用Store comonad的事实有关吗?还是我犯了一个明显的错误?据我所知,其他的实现,这是基于拉链comonad,是有效的.
import Control.Comonad data Store s a = Store (s -> a) s instance Functor (Store s) where fmap f (Store g s) = Store (f . g) s instance Comonad (Store s) where extract (Store f a) = f a duplicate (Store f s) = Store (Store f) s type Pos = (Int, Int) seed :: Store Pos Bool seed = Store g (0, 0) where g ( 0, 1) = True g ( 1, 0) = True g (-1, -1) = True g (-1, 0) = True g (-1, 1) = True g _ = False neighbours8 :: [Pos] neighbours8 = [(x, y) | x <- [-1..1], y <- [-1..1], (x, y) /= (0, 0)] move :: Store Pos a -> Pos -> Store Pos a move (Store f (x, y)) (dx, dy) = Store f (x + dx, y + dy) count :: [Bool] -> Int count = length . filter id getNrAliveNeighs :: Store Pos Bool -> Int getNrAliveNeighs s = count $ fmap (extract . move s) neighbours8 rule :: Store Pos Bool -> Bool rule s = let n = getNrAliveNeighs s in case (extract s) of True -> 2 <= n && n <= 3 False -> n == 3 blockToStr :: [[Bool]] -> String blockToStr = unlines . fmap (fmap f) where f True = '*' f False = '.' getBlock :: Int -> Store Pos a -> [[a]] getBlock n store@(Store _ (x, y)) = [[extract (move store (dx, dy)) | dy <- yrange] | dx <- xrange] where yrange = [(x - n)..(y + n)] xrange = reverse yrange example :: IO () example = putStrLn $ unlines $ take 7 $ fmap (blockToStr . getBlock 5) $ iterate (extend rule) seed
leftaroundab.. 6
商店comonad本身并不真正存储任何东西(除了抽象意义上的函数是一个"容器"),但必须从头开始计算它.这显然在几次迭代中变得非常低效.
如果您只是s -> a
通过一些备忘录来备份函数,那么您可以在不更改代码的情况下缓解此问题:
import Data.MemoTrie instance HasTrie s => Functor (Store s) where fmap f (Store g s) = Store (memo $ f . g) s instance HasTrie s => Comonad (Store s) where extract (Store f a) = f a duplicate (Store f s) = Store (Store f) s
没有测试这是否真的给出了可接受的性能.
商店comonad本身并不真正存储任何东西(除了抽象意义上的函数是一个"容器"),但必须从头开始计算它.这显然在几次迭代中变得非常低效.
如果您只是s -> a
通过一些备忘录来备份函数,那么您可以在不更改代码的情况下缓解此问题:
import Data.MemoTrie instance HasTrie s => Functor (Store s) where fmap f (Store g s) = Store (memo $ f . g) s instance HasTrie s => Comonad (Store s) where extract (Store f a) = f a duplicate (Store f s) = Store (Store f) s
没有测试这是否真的给出了可接受的性能.