phadej / vec

Nat, Fin, Vec

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Generalize and expose the conversion machienery

ShapeOfMatter opened this issue · comments

I've been playing around with functions to build Vec n as from infinite Streams and state-like functions (e.g.). We could certainly have a function like fromFunctor :: (Functor f1, Applicative f2) => ... -> f1 a -> f2 (Vec n a). This would be able to subsume* the existing implementations of fromListPrefix and fromList.

* fromListPrefix certainly; fromList may be a proud nail.

Here's what I've got so far:

newtype FromFunctor f1 f2 n a = FromFunctor { getFromFunctor :: (Functor f1, Functor f2) => f1 a -> f2 (Vec n a) }

fromFunctor :: forall f1 f2 n a.
               (SNatI n, Functor f1, Applicative f2) =>
               (f1 a -> f2 a) -> 
               (f1 a -> f1 a) ->
               f1 a -> f2 (Vec n a)
fromFunctor mkHead mkTail = getFromFunctor $ induction1 start step
  where start :: FromFunctor f1 f2 'Z a
        start = FromFunctor $ const $ pure VNil
        step :: forall m. FromFunctor f1 f2 m a -> FromFunctor f1 f2 ('S m) a
        step (FromFunctor f) = FromFunctor $ \f_1 -> (:::) <$> (mkHead f_1) <*> (f $ mkTail f_1)

-- These usage examples, while useful, would involve new dependencies: 

fromStream :: SNatI n => Stream a -> Vec n a
fromStream = runIdentity . (fromFunctor (Identity . Data.Stream.head) Data.Stream.tail)

unfold :: forall s n a.
          SNatI n =>
          (s -> (a, s)) ->
          (s -> (Vec n a, s))
unfold = runState . (fromFunctor id id) . state

Would you like me to put together a pull request?