-
Notifications
You must be signed in to change notification settings - Fork 14
Add scanr, scanl, scanr1, scanl1 #92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| {-# LANGUAGE BangPatterns #-} | ||
| {-# LANGUAGE CPP #-} | ||
| {-# LANGUAGE DataKinds #-} | ||
| {-# LANGUAGE FlexibleInstances #-} | ||
|
|
@@ -51,6 +52,13 @@ module Data.Vec.Lazy.Inline ( | |
| ifoldMap1, | ||
| foldr, | ||
| ifoldr, | ||
| -- * Scans | ||
| scanr, | ||
| scanl, | ||
| scanl', | ||
| scanr1, | ||
| scanl1, | ||
| scanl1', | ||
| -- * Special folds | ||
| length, | ||
| null, | ||
|
|
@@ -260,10 +268,10 @@ last :: forall n a. N.SNatI n => Vec ('S n) a -> a | |
| last xs = getLast (N.induction1 start step) xs where | ||
| start :: Last 'Z a | ||
| start = Last $ \(x:::VNil) -> x | ||
|
|
||
| step :: Last m a -> Last ('S m) a | ||
| step (Last rec) = Last $ \(_ ::: ys) -> rec ys | ||
|
|
||
|
|
||
| newtype Last n a = Last { getLast :: Vec ('S n) a -> a } | ||
|
|
||
|
|
@@ -274,7 +282,7 @@ init :: forall n a. N.SNatI n => Vec ('S n) a -> Vec n a | |
| init xs = getInit (N.induction1 start step) xs where | ||
| start :: Init 'Z a | ||
| start = Init (const VNil) | ||
|
|
||
| step :: Init m a -> Init ('S m) a | ||
| step (Init rec) = Init $ \(y ::: ys) -> y ::: rec ys | ||
|
|
||
|
|
@@ -520,6 +528,63 @@ ifoldr = getIFoldr $ N.induction1 start step where | |
|
|
||
| newtype IFoldr a n b = IFoldr { getIFoldr :: (Fin n -> a -> b -> b) -> b -> Vec n a -> b } | ||
|
|
||
| -- | Right-to-left scan. | ||
| scanr :: forall a b n. N.SNatI n => (a -> b -> b) -> b -> Vec n a -> Vec ('S n) b | ||
| scanr f z = getScanr $ N.induction1 start step where | ||
| start :: Scanr a 'Z b | ||
| start = Scanr $ \_ -> singleton z | ||
|
|
||
| step :: Scanr a m b -> Scanr a ('S m) b | ||
| step (Scanr go) = Scanr $ \(x ::: xs) -> case go xs of | ||
| ys@(y ::: _) -> f x y ::: ys | ||
|
|
||
| newtype Scanr a n b = Scanr { getScanr :: Vec n a -> Vec ('S n) b } | ||
|
|
||
| -- | Left-to-right scan. | ||
| scanl :: forall a b n. N.SNatI n => (b -> a -> b) -> b -> Vec n a -> Vec ('S n) b | ||
| scanl f = getScanl $ N.induction1 start step where | ||
| start :: Scanl a 'Z b | ||
| start = Scanl $ \z VNil -> singleton z | ||
|
|
||
| step :: Scanl a m b -> Scanl a ('S m) b | ||
| step (Scanl go) = Scanl $ \acc (x ::: xs) -> acc ::: go (f acc x) xs | ||
|
|
||
| -- | Left-to-right scan with strict accumulator. | ||
| scanl' :: forall a b n. N.SNatI n => (b -> a -> b) -> b -> Vec n a -> Vec ('S n) b | ||
| scanl' f = getScanl $ N.induction1 start step where | ||
| start :: Scanl a 'Z b | ||
| start = Scanl $ \z VNil -> singleton z | ||
|
|
||
| step :: Scanl a m b -> Scanl a ('S m) b | ||
| step (Scanl go) = Scanl $ \(!acc) (x ::: xs) -> acc ::: go (f acc x) xs | ||
|
|
||
| newtype Scanl a n b = Scanl { getScanl :: b -> Vec n a -> Vec ('S n) b } | ||
|
|
||
| -- | Right-to-left scan with no starting value. | ||
| scanr1 :: forall a n. N.SNatI n => (a -> a -> a) -> Vec n a -> Vec n a | ||
| scanr1 f = getScanr1 $ N.induction1 start step where | ||
| start :: Scanr1 'Z a | ||
| start = Scanr1 $ \_ -> VNil | ||
|
|
||
| step :: forall m. N.SNatI m => Scanr1 m a -> Scanr1 ('S m) a | ||
| step (Scanr1 go) = Scanr1 $ \(x ::: xs) -> case N.snat :: N.SNat m of | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't feel right. You shouldn't need to check length in the step case. I can take a look myself if you cannot find a way to avoid it.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @phadej - let me know if you have any updates on this! |
||
| N.SZ -> x ::: VNil | ||
| N.SS -> case go xs of ys@(y ::: _) -> f x y ::: ys | ||
|
|
||
| newtype Scanr1 n a = Scanr1 { getScanr1 :: Vec n a -> Vec n a } | ||
|
|
||
| -- | Left-to-right scan with no starting value. | ||
| scanl1 :: forall a n. N.SNatI n => (a -> a -> a) -> Vec n a -> Vec n a | ||
| scanl1 f xs = case N.snat :: N.SNat n of | ||
| N.SZ -> VNil | ||
| N.SS -> case xs of y ::: ys -> scanl f y ys | ||
|
|
||
| -- | Left-to-right scan with no starting value, and with strict accumulator. | ||
| scanl1' :: forall a n. N.SNatI n => (a -> a -> a) -> Vec n a -> Vec n a | ||
| scanl1' f xs = case N.snat :: N.SNat n of | ||
| N.SZ -> VNil | ||
| N.SS -> case xs of y ::: ys -> scanl' f y ys | ||
|
|
||
| -- | Yield the length of a 'Vec'. /O(n)/ | ||
| length :: forall n a. N.SNatI n => Vec n a -> Int | ||
| length _ = getLength l where | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.