-- Copyright (C) 2017-2018 Matthew Harm Bekkema -- -- This file is part of myanimelist-export. -- -- myanimelist-export is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- myanimelist-export is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . module MemoizedTraverse (memoizedTraverse) where import Data.Foldable import Data.Map.Strict (Map) import qualified Data.Map.Strict as M memoizedTraverse :: (Applicative f, Functor t, Foldable t, Ord a) => (a -> f b) -> t a -> f (t b) memoizedTraverse f xs = vals <&> \vals' -> lookupErr "myanimelist-export:memoizedTraverse: lookup error" vals' <$> xs where keys = foldl' (\acc x -> M.insert x () acc) M.empty xs vals = M.traverseWithKey (\k () -> f k) keys lookupErr :: Ord a => String -> Map a b -> a -> b lookupErr e = flip (M.findWithDefault (error e)) (<&>) :: Functor f => f a -> (a -> b) -> f b (<&>) = flip fmap