Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficiency of equality in Haskell

I've got a function that takes data and either returns the same data or a slightly modified version.

I want to have my program do one thing if it changed or another thing if it did not change.

Previously I was returning a pair (Bool,Object) and using fst to check if it changed. Lately it occurred to me that I could simplify the code by just returning the object and checking equality using ==.

But then I realized that Haskell doesn't differentiate between deep equality checking and "object identity" (i.e., pointer equality). So how can I know whether using == is going to be efficient or not? Should I avoid it for efficiency reasons, or are there cases where I can depend on the compiler figuring out that it doesn't need to do a deep equality check?

Normally I wouldn't be too worried about efficiency while writing an initial program, but this affects the interface to my module so I want to get it right before writing too much code, and it doesn't seem worth it to make the program much less efficient just to simply a small piece of code. Moreover, I'd like to get a better idea of what kind of optimizations I can depend on GHC to help me with.

like image 530
Steve Avatar asked Dec 29 '09 18:12

Steve


People also ask

What does == mean in Haskell?

The == is an operator for comparing if two things are equal. It is quite normal haskell function with type "Eq a => a -> a -> Bool". The type tells that it works on every type of a value that implements Eq typeclass, so it is kind of overloaded.

Can functions be compared for equality in Haskell?

Equality is defined to hold when all three of these parts of two functions are respectively equal. That means that any two functions can be compared for equality. Most notably, in Haskell, functions are not in the Eq typeclass (in general). Not any two functions can be compared for equality in Haskell.

How do you find type in Haskell?

If you are using an interactive Haskell prompt (like GHCi) you can type :t <expression> and that will give you the type of an expression. e.g. or e.g.


1 Answers

It's always a bad idea to rely on uncertain compiler optimizations to provide such an important performance guarantee as constant-time equality vs linear-time deep equality. You're much better off with a new type that encapsulates a value plus information about whether the value is new. Depending on your application this can be either

data Changed a = Changed a | Unchanged a

or

data Changed a = Changed a | Unchanged

We actually use a similar type inside the Glasgow Haskell Compiler so we can keep running the optimizer until the code stops changing. We also run iterative dataflow analysis until the results stop changing.

We found it useful to make this type a monad so that we can write some simple higher-order functions using do notation, but it's not necessary—just a convenience.

Summary: If you want constant-time checking, code it yourself—don't rely on a possible compiler optimization which might not be there—or which might change in the next release.

like image 165
Norman Ramsey Avatar answered Nov 10 '22 11:11

Norman Ramsey