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

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T19:35:58+00:00 2026-05-23T19:35:58+00:00

I am new to haskell and I encountered a performance issue that is so

  • 0

I am new to haskell and I encountered a performance issue that is so grave that it must be my code and not the haskell platform.

I have a python implementation of the Levenshtein distance (own code) and I passed (or tried to do so) this to haskell. The result is the following:

bool2int :: Bool -> Int
bool2int True = 1
bool2int False = 0

levenshtein :: Eq a => [a] -> [a] -> Int -> Int -> Int
levenshtein u v 0 0 = 0
levenshtein u v i 0 = i
levenshtein u v 0 j = j
levenshtein u v i j = minimum [1 + levenshtein u v i (j - 1),
    1 + levenshtein u v (i - 1) j,
    bool2int (u !! (i - 1) /= v !! (j - 1) ) + levenshtein u v (i - 1) (j - 1) ]

distance :: Eq a => [a] -> [a] -> Int
distance u v = levenshtein u v (length u) (length v)

Now, the difference in execution time for strings of length 10 or more is of various powers of 10 between python and haskell. Also with some rough time measuring (wall clock, as I haven’t found a clock() command in haskell so far) it seems that my haskell implementation has not cost O(mn), but some other exorbitantly fast growing cost.

Nota bene: I do not want my haskell implementation to compete speed wise with the python script. I just want it to run in a “sensible” time and not in multiples of the time the whole universe exists.

Questions:

  • What am I doing wrong, that my implementation is so darn slow?
  • How to fix it?
  • Talking about “lazy evaluation”: I gather that if levenshtein "cat" "kit" 2 2 is called thrice, it is only calculated once. Is this right?
  • There must be something built-in for my bool2int, right?
  • Any other input is highly appreciated if it shoves me ahead on the rough path to mastering haskell.

EDIT: Here goes the python code for comparison:

#! /usr/bin/python3.2
# -*- coding, utf-8 -*-

class Levenshtein:
        def __init__ (self, u, v):
                self.__u = ' ' + u
                self.__v = ' ' + v
                self.__D = [ [None for x in self.__u] for x in self.__v]
                for x, _ in enumerate (self.__u): self.__D [0] [x] = x
                for x, _ in enumerate (self.__v): self.__D [x] [0] = x

        @property
        def distance (self):
                return self.__getD (len (self.__v) - 1, len (self.__u) - 1)

        def __getD (self, i, j):
                if self.__D [i] [j] != None: return self.__D [i] [j]
                self.__D [i] [j] = min ( [self.__getD (i - 1, j - 1) + (0 if self.__v [i] == self.__u [j] else 1),
                                  self.__getD (i, j - 1) + 1,
                                  self.__getD (i - 1, j) + 1] )
                return self.__D [i] [j]

print (Levenshtein ('first string', 'second string').distance)
  • 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-23T19:35:58+00:00Added an answer on May 23, 2026 at 7:35 pm

    What am I doing wrong, that my implementation is so darn slow?

    Your algorithm has exponential complexity. You seem to be assuming that the calls are being memoized for you, but that’s not the case.

    How to fix it?

    You’ll need to add explicit memoization, possibly using an array or some other method.

    Talking about “lazy evaluation”: I gather that if levenshtein "cat" "kit" 2 2 is called thrice, it is only calculated once. Is this right?

    No, Haskell does not do automatic memoization. Laziness means that if you do let y = f x in y + y, then the f x will only be evaluated (once) if the result of the sum is demanded. It does not mean that f x + f x will evaluate in only one call to f x. You have to be explicit when you want to share results from subexpressions.

    There must be something built-in for my bool2int, right?

    Yes, there is an instance Enum Bool, so you can use fromEnum.

    *Main> fromEnum True
    1
    *Main> fromEnum False
    0
    

    Any other input is highly appreciated if it shoves me ahead on the rough path to mastering haskell.

    While writing stuff from scratch may be fun and educational, it is important to learn to take advantage of the many great libraries on Hackage when doing common things like this.

    For example there is an implementation of the Levenshtein distance in the edit-distance package.


    I translated your Haskell code back to Python for comparison:

    def levenshtein(u, v, i, j):
        if i == 0: return j
        if j == 0: return i
    
        return min(1 + levenshtein(u, v, i, (j-1)),
                   1 + levenshtein(u, v, (i-1), j),
                   (u[i-1] != v[j-1]) + levenshtein(u, v, (i-1), (j-1)))
    
    def distance(u, v):
        return levenshtein(u, v, len(u), len(v))
    
    if __name__ == "__main__":
        print distance("abbacabaab", "abaddafaca")
    

    Even without fixing the O(n) indexing issue that chrisdb pointed out in his answer, this performs slower than the Haskell version when compiled:

    $ time python levenshtein.py
    6
    
    real    0m4.793s
    user    0m4.690s
    sys 0m0.020s
    
    $ time ./Levenshtein 
    6
    
    real    0m0.524s
    user    0m0.520s
    sys 0m0.000s
    

    Of course, they both lose to the properly memoized version in the edit-distance package:

    $ time ./LevenshteinEditDistance 
    6
    
    real    0m0.015s
    user    0m0.010s
    sys 0m0.000s
    

    Here’s a simple memoized implementation using Data.Array:

    import Data.Array
    
    distance u v = table ! (m, n)
       where table = listArray ((0, 0), (m, n)) [levenshtein i j | i <- [0..m], j <- [0..n]]
    
             levenshtein 0 j = j
             levenshtein i 0 = i
             levenshtein i j = minimum [ 1 + table!(i, j-1)
                                       , 1 + table!(i-1, j)
                                       , fromEnum (u'!(i-1) /= v'!(j-1)) + table!(i-1, j-1) ]
    
             u' = listArray (0, m-1) u
             v' = listArray (0, n-1) v
    
             m = length u
             n = length v
    
    main = print $ distance "abbacabaab" "abaddafaca"
    

    It performs similarly to your original Python code:

    $ time python levenshtein-original.py 
    6
    
    real    0m0.037s
    user    0m0.030s
    sys 0m0.000s
    $ time ./LevenshteinArray 
    6
    
    real    0m0.017s
    user    0m0.010s
    sys 0m0.000s
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

New to Haskell and have a stumbling block. I'm trying to filter a list
Im new to Haskell!! I wrote this code: import Data.List inputIndex :: [String] ->
I am new to Haskell and facing a "cannot construct infinite type" error that
I am new at haskell, I have to write a program context-aware,so I thought
I am new to Haskell,I should write a function that takes a function among
Im pretty new to Haskell. I have a datatype: data Sentence= Prop Int |
[Disclaimer] I am very new to Haskell (and any FPL for that matter), just
I have a new web app that is packaged as a WAR as part
I'm new to Haskell, so am sorry if this is incredibly obvious... I have
I'm fairly new to Haskell and have a question about pattern-matching. Here is a

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.