The foldr identity is
foldr (:) []
More generally, with folds you can either destroy structure and end up with a summary value or inject structure in such a way that you end up with the same output structure.
[Int] -> [Int]
or
[Int] -> Int
or
[Int] -> ?
I'm wondering if there a similar identity with unfoldr/l.
I know how to get
Int -> [Int]
with unfold/ana.
I'm looking for some kind of way to go from
Int -> Int
with a recursion scheme.
Taking a cue from your remark about factorials, we can note that natural numbers can be treated as a recursive data structure:
In terms of the recursion-schemes machinery, the corresponding base functor would be:
NatF
, however, is isomorphic toMaybe
. That being so, recursion-schemes conveniently makesMaybe
the base functor of theNatural
type from base. For instance, here is the type ofana
specialised toNatural
:We can use it to write the identity unfold for
Natural
:The coalgebra we just gave to
ana
isproject
forNatural
,project
being the function that unwraps one layer of the recursive structure. In terms of the recursion-schemes vocabulary,ana project
is the identity unfold, andcata embed
is the identity fold. (In particular,project
for lists isuncons
fromData.List
, except that it is encoded withListF
instead ofMaybe
.)By the way, the factorial function can be expressed as a paramorphism on naturals (as pointed out in the note at the end of this question). We can also implement that in terms of recursion-schemes:
para
makes available, at each recursive step, the rest of the structure to be folded (if we were folding a list, that would be its tail). In this case, I have called the value thus providedpredec
because at then
-th recursive step from bottom to toppredec
isn - 1
.Note that user11228628's hylomorphism is probably a more efficient implementation, if you happen to care about that. (I haven't benchmarked them, though.)