Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 800549
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 14, 20262026-05-14T23:18:23+00:00 2026-05-14T23:18:23+00:00

The following simple function applies a given monadic function iteratively until it hits a

  • 0

The following simple function applies a given monadic function iteratively until it hits a Nothing, at which point it returns the last non-Nothing value. It does what I need, and I understand how it works.

lastJustM :: (Monad m) => (a -> m (Maybe a)) -> a -> m a
lastJustM g x = g x >>= maybe (return x) (lastJustM g)

As part of my self-education in Haskell I’m trying to avoid explicit recursion (or at least understand how to) whenever I can. It seems like there should be a simple non-explicitly recursive solution in this case, but I’m having trouble figuring it out.

I don’t want something like a monadic version of takeWhile, since it could be expensive to collect all the pre-Nothing values, and I don’t care about them anyway.

I checked Hoogle for the signature and nothing shows up. The m (Maybe a) bit makes me think a monad transformer might be useful here, but I don’t really have the intuitions I’d need to come up with the details (yet).

It’s probably either embarrassingly easy to do this or embarrassingly easy to see why it can’t or shouldn’t be done, but this wouldn’t be the first time I’ve used self-embarrassment as a pedagogical strategy.

Update: I could of course provide a predicate instead of using Maybe: something like (a -> Bool) -> (a -> m a) -> a (returning the last value for which the predicate is true) would work just as well. What I’m interested in is a way to write either version without explicit recursion, using standard combinators.


Background: Here’s a simplified working example for context: suppose we’re interested in random walks in the unit square, but we only care about points of exit. We have the following step function:

randomStep :: (Floating a, Ord a, Random a) =>
              a -> (a, a) -> State StdGen (Maybe (a, a))
randomStep s (x, y) = do
  (a, gen') <- randomR (0, 2 * pi) <$> get
  put gen'
  let (x', y') = (x + s * cos a, y + s * sin a)
  if x' < 0 || x' > 1 || y' < 0 || y' > 1
    then return Nothing
    else return $ Just (x', y')

Something like evalState (lastJustM (randomStep 0.01) (0.5, 0.5)) <$> newStdGen will give us a new data point.

  • 1 1 Answer
  • 1 View
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-14T23:18:23+00:00Added an answer on May 14, 2026 at 11:18 pm

    A lot of what avoiding explicit recursion is about is composing built-in recursive combinators, which usually work on very generic unlifted values. Doing the same thing in a Functor, Monad, or other lifted type sometimes works using basic lifting operations like fmap, <*>, >>=, and so on. In some cases a pre-lifted version is already present, as with mapM, zipWithM, and so on. Other times, as with takeWhile, lifting is not trivial and no built-in version is provided.

    Your function indeed has characteristics of something that should be a lifted version of standard combinators. So first, let’s strip out the monad to reconstruct the function you’re implicitly lifting:

    lastJust :: (a -> Maybe a) -> a -> a
    

    The word “last” here gives us a hint; non-explicit recursion often uses temporary lists as control structures. So what you want is last applied to the list generated by iterating the function until getting Nothing. With a slight generalization of the type, we find the generator:

    unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
    

    So we have something like this:

    dup x = (x, x)
    lastJust f x = last $ unfoldr (fmap dup . f) x
    

    Unfortunately at this point we’re kind of stuck, because (to my knowledge) there’s no monadic unfold and lifting it is, like takeWhile, not trivial. Another thing that could make sense is a more general unfold with a signature like (MonadMaybe m) => (b -> m (a, b)) -> b -> m [a] and an accompanying MaybeT transformer, but that doesn’t exist in the standard libraries either, and monad transformers are kind of a Pit of Despair anyway. A third approach might be to find some way to generalize both Maybe and the unknown monad out as MonadPlus or something similar.

    Of course, there may be other approaches with a different structure, but I suspect you’re likely to find similar awkwardness with any function that needs to be recursive going “into” a monad, e.g., each step conceptually introduces another layer that must be eliminated with >>=, join, etc.

    In summary: At first inspection your function as written is best expressed without explicit recursion, using a recursive combinator (some flavor of unfoldM) that doesn’t exist. You can either write the combinator yourself (as people have done with takeWhileM), go digging around on Hackage for monadic recursive combinators, or just leave your code as is.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 489k
  • Answers 489k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer if self.permission_index_link not in (0,8): # code Is this what… May 16, 2026 at 8:56 am
  • Editorial Team
    Editorial Team added an answer NB: See The Curse and Blessings of Dynamic SQL -… May 16, 2026 at 8:56 am
  • Editorial Team
    Editorial Team added an answer ltlText is unknown directly since it lives in a containing… May 16, 2026 at 8:56 am

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Related Questions

I have the following code that applies a XSLT style Test.Xml.xslTransform = function(xml, xsl)
The situation is simple. I have a datagrid that gets its data from a
I read Scott Meyers' article on the subject and quite confused about what he
I have done some web based projects, but I don't think too much about
I noticed it is possible to set the value of a jQuery UI slider
I'm trying to use jQuery to format code blocks, specifically to add a <pre>
I have some problems when I want to use implicit methods to convert a
We use g++ 4.2.4 and I'm trying to track down some performance problems in
Ok saddle up cowboys, because this is going to be a long one. I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.