content: -- | Simple structural conversions.
  module Analyze.Conversions
    ( projectRow
    , projectRows
    ) where
  
  import           Analyze.Common      (Data, MissingKeyError (..), makeLookup)
  import           Analyze.RFrame      (RFrame (..), RFrameUpdate (..), fromUpdate)
  import           Control.Monad.Catch (MonadThrow (..))
  import           Data.HashMap.Strict (HashMap)
  import qualified Data.HashMap.Strict as HM
  import           Data.Vector         (Vector)
  import qualified Data.Vector         as V
  
  -- | Projects values out of the map according to the given key order.
  projectRow :: (Data k, MonadThrow m) => Vector k -> HashMap k v -> m (Vector v)
  projectRow ks row = V.mapM f ks
    where
      f k =
        case HM.lookup k row of
          Nothing -> throwM (MissingKeyError k)
          Just v  -> pure v
  
  -- | Projects an 'RFrame' out of many maps according to the given key order.
  projectRows :: (Data k, MonadThrow m) => Vector k -> Vector (HashMap k v) -> m (RFrame k v)
  projectRows ks rs = do
    vs <- V.mapM (projectRow ks) rs
    fromUpdate (RFrameUpdate ks vs)
  