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 7726991
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 1, 20262026-06-01T05:20:54+00:00 2026-06-01T05:20:54+00:00

This function is much faster than its recursive version: crossSubstrings :: String -> String

  • 0

This function is much faster than its recursive version:

crossSubstrings :: String -> String -> [(String,String)]
crossSubstrings string1 string2 = [(substr1,substr2) | substr1 <- inits string1,
                                                       substr2 <- inits string2]

type Distances = Map.Map (String,String) Int

editDistanceMemoized :: String -> String -> Int
editDistanceMemoized s1 s2 = 
   let 
     substrings = s1 `crossSubstrings` s2
     distances = foldl (editDistance) emptyMap substrings
   in
     distances Map.! (s1,s2)
   where 
     emptyMap = Map.fromList []
     editDistance :: Distances -> (String,String) -> Distances
     editDistance map ([],s1) = map `Map.union` getMap [] s1 (length s1)
     editDistance map (s1,[]) = map `Map.union` getMap s1 [] (length s1)
     editDistance map (s1,s2) = map `Map.union` getMap s1 s2 (cost map s1 s2)
     getMap s1 s2 d = Map.fromList [((s1,s2),d)]
     insertionPCost = \m -> \s1 -> \s2 -> m Map.! (s1, init s2) + 1
     deletionPCost = \m -> \s1 -> \s2 -> m Map.! (init s1, s2)  + 1
     substitutionPCost = \m -> \s1 -> \s2 -> m Map.! (init s1, init s2)
                                             + substitutionCostIfNEQ s1 s2
     substitutionCostIfNEQ = \s1 -> \s2 -> if (last s1 == last s2) then 0 else 2
     cost = \m -> \s1 -> \s2 -> minimum [insertionPCost m s1 s2,
                                         deletionPCost m s1 s2,
                                         substitutionPCost m s1 s2] 

However (first question), I feel like some lambdas could be avoided (doesn’t it look repetitive? look specially at cost). Is there a way to compose minimum ?

In addition, the State Monad could be used to propagate the map (instead of using foldl?). Despite despite reading how State.>>= and State.id behave, I’m not 100% sure how the signature should look like (second question).

I thought of this one, where the state is “the next pair of strings to be measured” and Distances contains the memoized distances.

 editDistance :: State Distances (String,String) -> State Distances ()?
  • 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-06-01T05:20:56+00:00Added an answer on June 1, 2026 at 5:20 am

    insertionPCost, deletionPCost, substitutionPCost and substitutionCostIfNEQ are only called from each other and cost, and always with the same arguments (save that substitutionCostIfNEQ doesn’t take m); so we can rearrange them like this:

    cost = \m -> \s1 -> \s2 -> minimum [insertionPCost, deletionPCost, substitutionPCost] 
      where insertionPCost = m Map.! (s1, init s2) + 1
            deletionPCost = m Map.! (init s1, s2)  + 1
            substitutionPCost = m Map.! (init s1, init s2) + substitutionCostIfNEQ
            substitutionCostIfNEQ = if (last s1 == last s2) then 0 else 2
    

    And the explicit lambdas aren’t getting you anything, so rewrite to be clearer:

    cost m s1 s2 = minimum [insertionPCost, deletionPCost, substitutionPCost] 
      where insertionPCost = m Map.! (s1, init s2) + 1
            deletionPCost = m Map.! (init s1, s2)  + 1
            substitutionPCost = m Map.! (init s1, init s2) + substitutionCostIfNEQ
            substitutionCostIfNEQ = if (last s1 == last s2) then 0 else 2
    

    To answer your second question, currently you have

    editDistance :: Distances -> (String,String) -> Distances
    

    If you were to use State instead, that would be

    editDistance :: (String,String) -> State Distances ()
    

    That is, editDistance would be a function that takes (String,String), and yields something that interacts with a Distances state, and no other meaningful result.

    But.

    Firstly, I don’t see that there’s anything wrong with your use of foldl.

    Secondly, you never really use the accumulated value, what would be the state. You use it to make a new value, but you don’t look anything up in it. So you don’t need State, you only need Writer.

    editDistance :: (String,String) -> Writer Distances ()
    

    That is, editDistance would be a function that takes (String,String), and yields something that adds to a Distances accumulator, and no other meaningful result.

    (There’s a subtlety here: the first parameter to Writer has to be a Monoid, and it has to use the combining operation (mappend) that’s useful to you; well, Maps are Monoids, and their mappend is the same union that you use in your original editDistance, so it all works out fine.)

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

Sidebar

Related Questions

I've simplified this example as much as I can. I have a remote function:
I'm fairly new to C, not having much need to anything faster than python
This function declaration gives me errors: ostream& operator<<(ostream& os, hand& obj); The errors are:
This function is written in ActionScirpt. What kind of decryption this is? Is there
This function of mine keeps on failing an autograder, I am trying to figure
This function creates & stores a cookie, and here it stores the name of
This function gives me the following error: SyntaxError: Invalid character '\u8203' All looks good
This function is driving me insane! def CCAD1 (tree) leaves = [] for otu
This function is O(log(n)). Why? Isn't it looping up to n? function fxn($n) {
Since this function is implemented in IE8, I wanted to see exactly what 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.