haskellrecursiontype-inferencerecursion-schemesfoldable# How can I avoid explicit recursion in this case?

I wound up with this skeleton:

```
f :: (Monad m) => b -> m ()
f x = traverse_ (f . g x) =<< h x -- how avoid explicit recursion?
g :: b -> a -> b
-- h :: (Foldable t) => b -> m (t a) -- why "Could not deduce (Foldable t0) arising from a use of ‘traverse_’"
h :: b -> m [a]
```

How can I avoid the explicit recursion in `f`

?

Bonus: When I try to generalize `h`

from `[]`

to `Foldable`

, `f`

does not type check (`Could not deduce (Foldable t0) arising from a use of ‘traverse_’`

) -- what am I doing wrong?

UPDATE:
Here's the real code. The `Right`

side is for recursing down directories of security camera footage whose names are integers. `Left`

is the base case to process leaves whose names are not integers.

```
a <|||> b = left a . right b
doDir (Right d) = traverse_ (doDir . doInt) =<< listDirectory d
where doInt s = ((<|||>) <$> (,) <*> const) (d </> s) $ (TR.readEither :: String -> Either String Int) s
```

`f = doDir`

and `g ~ doInt`

but got refactored a little. `h = listDirectory`

. to answer the bonus, i was just being silly and wasn't seeing that i had to combine all the definitions to bind the types together:

```
f :: (Monad m, Foldable t) => (b -> a -> b) -> (b -> m (t a)) -> b -> m ()
f g h x = traverse_ (f g h . g x) =<< h x
```

Solution

If you don't mind leaking a bit of memory building a `Tree`

and then throwing it away, you can use `unfoldTreeM`

:

```
f = unfoldTreeM (\b -> (\as -> ((), g b <$> as)) <$> h b)
```

I do not believe there is a corresponding `unfoldTreeM_`

, but you could write one (using explicit recursion). To generalize beyond the `Tree`

/`[]`

connection, you might also like `refoldM`

; you can find several similar functions if you search for "hylomorphism" on Hackage.

- Comparing lists in Haskell
- Is there a non-identity monad morphism M ~> M that is monadically natural in M?
- Problem with loading module ‘Distribution.Simple’
- Improving efficiency in Stirling numbers calculation
- Does sequencing an infinite list of IO actions by definition result in a never-ending action? Or is there a way to bail out?
- How to call pgQuery from postgresql-query?
- How to avoid whitespace after a tag (link) in Hamlet templates?
- Understanding type-directed resolution in Haskell with existential types
- Why is seq bad?
- Understanding bind function in Haskell
- How to create route that will trigger on any path in Servant?
- How do I use a global state in WAI middleware?
- nixos 23.11 cabal install mysql-simple problem - "Missing (or bad) C libraries"
- Is there a way to kill all forked threads in a GHCi session without restarting it?
- Why can an invalid list expression such as 2:1 be assigned to a variable, but not printed?
- Iterate over a type level list and call a function based on each type in the list
- How does this solution of Project Euler Problem 27 in the Haskell Wiki work?
- Why `Monad` is required to use `pure`?
- Can't do partial function definitions in GHCi
- recommended way to convert Double -> Float in Haskell
- Haskell profiling understanding cost centre summary for anonymous lambda
- Why is Haskell fully declarative?
- GHC Generating Redundant Core Operations
- Question about Event firing in reflex-frp
- Using Haskell's "Maybe", type declarations
- How can I elegantly invert a Map's keys and values?
- Why there is no output for wrapped IO in Haskell?
- What are the definitions of Weather and Memory in xmobar repo?
- Serializing a Data.Text value to a ByteString without unnecessary \NUL bytes
- Using Haskell with VS Code