Generalize and expose the conversion machienery
ShapeOfMatter opened this issue · comments
I've been playing around with functions to build Vec n a
s 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?