-- | -- Module : Data.SubG.Unfold -- Copyright : (c) OleksandrZhabenko 2021-2023 -- License : MIT -- Stability : Experimental -- Maintainer : oleksandr.zhabenko@yahoo.com -- -- Generalization of the 'Data.List.unfoldr' for the data type that has 'InsertLeft' and 'Monoid' instances. -- Inspired by: https://www.works-hub.com/learn/number-anamorphisms-aka-unfolds-explained-50e1a by Marty Stumpf. {-# LANGUAGE NoImplicitPrelude #-} module Data.SubG.Unfold ( unfoldG , iterateG ) where import GHC.Base import Data.SubG import Data.Monoid -- | Inspired by: https://hackage.haskell.org/package/base-4.14.0.0/docs/src/Data.OldList.html#words -- and: Graham Hutton. A tutorial on the universality and expressiveness of fold. /J. Functional Programming/ 9 (4): 355–372, July 1999. -- that is available at the URL: https://www.cs.nott.ac.uk/~pszgmh/fold.pdf. -- Also inspired by: https://www.works-hub.com/learn/number-anamorphisms-aka-unfolds-explained-50e1a by Marty Stumpf. -- Generalizes the 'Data.List.unfoldr' function not only for lists, but for the data type that has 'InsertLeft' and 'Monoid' instances. unfoldG :: (InsertLeft t a, Monoid (t a)) => (b -> Maybe (a, b)) -> b -> t a unfoldG :: forall (t :: * -> *) a b. (InsertLeft t a, Monoid (t a)) => (b -> Maybe (a, b)) -> b -> t a unfoldG b -> Maybe (a, b) p b x = case b -> Maybe (a, b) p b x of Just (a y, b z) -> a y forall (t :: * -> *) a. InsertLeft t a => a -> t a -> t a %@ forall (t :: * -> *) a b. (InsertLeft t a, Monoid (t a)) => (b -> Maybe (a, b)) -> b -> t a unfoldG b -> Maybe (a, b) p b z Maybe (a, b) Nothing -> forall a. Monoid a => a mempty -- | Inspired by: https://hackage.haskell.org/package/base-4.14.0.0/docs/src/Data.OldList.html#words -- and: Graham Hutton. A tutorial on the universality and expressiveness of fold. /J. Functional Programming/ 9 (4): 355–372, July 1999. -- that is available at the URL: https://www.cs.nott.ac.uk/~pszgmh/fold.pdf. -- Also inspired by: https://www.works-hub.com/learn/number-anamorphisms-aka-unfolds-explained-50e1a by Marty Stumpf. -- Generalizes the 'Prelude.iterate' function not only for lists, but for the data type that has 'InsertLeft' and 'Monoid' instances. iterateG :: (InsertLeft t a, Monoid (t a)) => (a -> a) -> a -> t a iterateG :: forall (t :: * -> *) a. (InsertLeft t a, Monoid (t a)) => (a -> a) -> a -> t a iterateG a -> a f = forall (t :: * -> *) a b. (InsertLeft t a, Monoid (t a)) => (b -> Maybe (a, b)) -> b -> t a unfoldG (\a x -> forall a. a -> Maybe a Just (a x, a -> a f a x)) {-# INLINE iterateG #-}