Skip to content

Latest commit

 

History

History
61 lines (50 loc) · 1.34 KB

length-matched-vectors.md

File metadata and controls

61 lines (50 loc) · 1.34 KB

Length matched vectors

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}
module VectorLenMatched
   ( VectorLM
   , LMKey
   , lmKeys
   , unVectorLM
   , lookupVectorLM
   , withVectorLM
   , newVectorLM
   , unknownKey
   ) where

import RIO
import qualified RIO.Vector as V
import RIO.Vector.Unsafe (unsafeIndex)
import Data.Proxy
import Data.Reflection
import Data.Void

newtype LMKey k = LMKey Int

newtype VectorLM k a = VectorLM (Vector a)

unknownKey :: Vector a -> VectorLM () a
unknownKey = VectorLM

unVectorLM :: VectorLM k a -> Vector a
unVectorLM (VectorLM v) = v

lookupVectorLM :: LMKey k -> VectorLM k a -> a
lookupVectorLM (LMKey idx) (VectorLM v) = unsafeIndex v idx

lmKeys :: forall k. Reifies k Int => [LMKey k]
lmKeys =
  case reflect (Proxy :: Proxy k) of
    0 -> []
    i -> map LMKey [0..i - 1]

withVectorLM
  :: forall a r.
     Vector a
  -> (forall k. Reifies k Int => VectorLM k a -> r)
  -> r
withVectorLM v inner = reify (V.length v) $ \p -> inner $ addType p v

addType :: proxy k -> Vector a -> VectorLM k a
addType _ = VectorLM

newVectorLM :: forall k a. Reifies k Int => Vector a -> Maybe (VectorLM k a)
newVectorLM v
  | V.length v == len = Just (VectorLM v)
  | otherwise = Nothing
  where
    len = reflect (Proxy :: Proxy k)