-- 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 <https://www.gnu.org/licenses/>.

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