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

  • SEARCH
  • Home
  • 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 6001523
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T00:50:48+00:00 2026-05-23T00:50:48+00:00

So I was thinking about a graph distance algorithm tonight, and came up with

  • 0

So I was thinking about a graph distance algorithm tonight, and came up with this
while I was driving in the car:

module GraphDistance where
import Data.Map

distance :: (Ord a) => a -> Map a [a] -> Map a Int
distance a m = m' 
  where m' = mapWithKey d m
        d a' as = if a == a' then 0 else 1 + minimum (Prelude.map (m'!) as)

At first, I was fairly proud of myself, since it seemed so elegant.
But then I realized it wouldn’t work – the corecursion might get stuck
in a loop.

I had to code it up to convince myself:

ghci> distance 1 $ fromList [(0,[1]),(1,[0,2]),(2,[1,3]),(3,[2])]
fromList [(0,1),(1,0),(2,^CInterrupted.

But now I think I’ve pretty much thought it through.

Is there a list of common errors and anti-patterns
when dealing with corecursive data that I can go read up on,
so I can train my brain to think corecursively? Experience
has trained me fairly well for thinking through non-corecursive
data, but I’d like to learn from others mistakes if I can.

  • 1 1 Answer
  • 0 Views
  • 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-23T00:50:48+00:00Added an answer on May 23, 2026 at 12:50 am

    Well, there’s really only one fundamental mistake when dealing with corecursive data, and that’s carelessly using recursion on it!

    Corecursion implies that data is being generated incrementally in some sense. Your graph distance function is instructive here, because it seems like it should work, so think about where the incremental part should be: The starting point is a distance of 0 from a node to itself, otherwise one greater than the minimum distance among its own immediate neighbors. Thus, we would expect each distance value to be incremental, which means we need them to be suitably corecursive themselves.

    The recursion at issue, then, is occurring due to the combination of (+) and minimum: when finding the minimum, 1 will always be less than 1 + n, without needing to worry about what n is… but there’s no way to compare Ints without computing the entire value.

    In short, the algorithm expects to be able to compare how many times (1 +) was applied to 0 only as far as needed; that is to say, it wants lazy natural numbers defined using “zero” and “successor”.

    Behold:

    data Nat = Z | S Nat
    
    natToInt :: Nat -> Int
    natToInt Z = 0
    natToInt (S n) = 1 + natToInt n
    
    instance Show Nat where show = show . natToInt
    
    instance Eq Nat where
        Z == Z = True
        (S n1) == (S n2) = n1 == n2
        _ == _ = False
    
        Z /= Z = False
        (S n1) /= (S n2) = n1 /= n2
        _ /= _ = True
    
    
    instance Ord Nat where
        compare Z Z = EQ
        compare Z (S _) = LT
        compare (S _) Z = GT
        compare (S n1) (S n2) = compare n1 n2
    

    And then in GHCi:

    > distance 1 $ fromList [(0,[1]),(1,[0,2]),(2,[1,3]),(3,[2])]
    fromList [(0,1),(1,0),(2,1),(3,2)]
    

    Proof that your algorithm works[0]; your implementation of it was just incorrect.


    Now, as a slight variation, let’s apply your algorithm to a different graph:

    > distance 1 $ fromList [(0,[1]),(1,[0]),(2,[3]),(3,[2])]
    

    …what do we expect this to do? What is the distance from node 1 for nodes 2 or 3?

    Running it in GHCi has the obvious result:

    fromList [(0,1),(1,0),(2,^CInterrupted.
    

    Nevertheless, the algorithm works correctly on this graph. Can you see the problem? Why did it hang in GHCi?


    In summary, you need to clearly distinguish between two forms that can’t be mixed freely:

    • Lazy, possibly infinite data, generated corecursively
    • Finite data, consumed recursively

    Both forms can be transformed in a structure-agnostic way (e.g., map works on finite and infinite lists both). Codata can be consumed incrementally, driven by a corecursive algorithm; data can be generated recursively, limited by a recursive algorithm.

    What you can’t do is consume codata recursively (e.g., left folding an infinite list) or generate data corecursively (rare in Haskell, due to laziness).

    [0]: Actually, it will fail on some inputs (e.g., some disconnected graphs), but that’s a different issue.

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

Sidebar

Related Questions

While thinking about this question and conversing with the participants, the idea came up
Been thinking about this for hours now. Im building a simple slideshow application, where
We're thinking about putting up a data warehouse system to load with web access
Thinking about monad, it came to me the idea of a monad as the
While thinking about the way to implement Scheme R5RS, I have become puzzled about
I was thinking about the algorithm of finding a negative weight cycle in a
I've been thinking about creating a class in C++ on graph theory. The idea
I'm working on data structure for graph cut algorithm. Problem is to make different
I'm thinking about a problem in graphs, one part of this problem is as
I am thinking about this topcoder problem . Given a string of digits, find

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.