Если вам нужна максимальная универсальность, вы можете запомнить функцию запоминания.
memo :: (Num a, Enum a) => (a -> b) -> [b]
memo f = map f (enumFrom 0)
gwvals = fmap memo (memo gw)
fastgw :: Int -> Int -> Int
fastgw x y = gwvals !! x !! y
Этот метод будет работать с функциями, имеющими любое количество аргументов.
Редактировать: благодаря Филиппу К.за указание на ошибку в исходном коде.Первоначально memo
имел ограничение «Ограничено» вместо «Num» и начинал перечисление с minBound
, что было бы допустимо только для натуральных чисел.
Списки не являются хорошей структурой данных для запоминания,хотя, потому что они имеют линейную сложность поиска.Вам может быть лучше с картой или IntMap.Или посмотрите на Hackage .
Обратите внимание, что этот конкретный код зависит от лени, поэтому, если вы хотите перейти на использование карты, вынужно будет взять ограниченное количество элементов из списка, как в:
gwByMap :: Int -> Int -> Int -> Int -> Int
gwByMap maxX maxY x y = fromMaybe (gw x y) $ M.lookup (x,y) memomap
where
memomap = M.fromList $ concat [[((x',y'),z) | (y',z) <- zip [0..maxY] ys]
| (x',ys) <- zip [0..maxX] gwvals]
fastgw2 :: Int -> Int -> Int
fastgw2 = gwByMap 20 20
Я думаю, что ghc может быть глупым из-за совместного использования в этом случае, вам может понадобиться убрать x
и y
параметры, как это:
gwByMap maxX maxY = \x y -> fromMaybe (gw x y) $ M.lookup (x,y) memomap