Code Monkey home page Code Monkey logo

Comments (3)

aspiwack avatar aspiwack commented on August 11, 2024 1

Oooff… I kind of forgot about this issue for a while. Sorry.

My intention with these is type is that

  • (==) :: a %1-> a %1-> (Bool, a, a) is a pretty awful type to work with
  • types that can implement the equality test above will be Dupable.

You come with two counter-example. Mutable arrays are not dupable, neither would mutable byte arrays. Nevertheless it may make sense to compare them.

  • You could have structural, $O(n)$, equality.
  • Pointer equality doesn't make much sense for these: it's always false
  • But you can have pointer comparisons for the sake of an ordered data structure. Probably not for mutable arrays, as this is not stable (it would have to be in IO); but for byte arrays that are pinned, it makes sense for comparison to be pure.

There is more than one way to think about this.

  • We can keep the classes as they are and say: this is the most common case, Dupable structures, and they're better types when working on them. But I see an issue there that hadn't surfaced yet: pretty much every data structure requiring an Ord instance will have to use Dupable as well. Dubious.
  • We can use your definitions, but then, when we always have to handle these pesky extra fields, even when we are in the Dupable case. Possible mitigation, add a copy of each method like so:
    class Eq a where
      (==:) :: a %1-> a %1-> (Bool, a, a)
      (==) :: Consumable a => a %1-> a %1-> Bool
      a == b = let !(r, a', b') = a ==: b in a' `lseq` b' `lseq` r
    But for Consumable data types, we can typically implement (==) directly, and bypass the extra call to consume/lseq.
  • Or we could say that we need to invent something new.

Let me riff on this third possibility for a little while.

We could say that, instead of (==), compare and all that, the proper primitive is compare-and-swap:

cas :: a %1 -> a %1 -> (a, a)

Where the guarantee is that in the returned pair, the smaller a is first. As an aside cas has well-defined laws, and is equivalent to lattices (maybe distributive, I don't remember) (it works for partial orderings, in which case the result is to be understood as $(a \wedge b, a \vee b)$).

It's quite clear that a linear cas is a perfectly reasonable construction.

However, it's far from perfect. For instance, you can't write quicksort or mergesort with cas (exercise: try). Sorting that can be done with cas are called network sorts, the most famous is the bitonic sort.

One key issue with cas is that it doesn't let us decide equality.

Ok, maybe let's add a boolean:

cas :: a %1 -> a %1 -> (Bool,a, a)

It's not much worse, and it's easy to produce a version that doesn't return the boolean. It does encode the additional ordering structure in the ordering of the pair. Pretty neat.

But I don't think it suffices for mergesort: at some point in merge sort you have (a : as) (b : bs), and you need to pick the smaller of a and b, and leave the other one in its place. So we really need to know which one was the smaller. The above type doesn't give it to us. So we'd need to know whether a reordering has happened. Basically

cas :: a %1 -> a %1 -> (Ordering, a, a)

This is your compare but the two returned a may have been permuted. Not a very useful “improvement”. It's interesting that with a boolean we could still encode some data in the choice of which a to return in which place, but this isn't the case as soon as we add just a third alternative.

Well… I wrote a lot of words, not many are useful, are they?

from linear-base.

treeowl avatar treeowl commented on August 11, 2024

A couple examples:

  1. Comparing two mutable arrays for (pointer) equality should not consume them.
  2. Comparing the addresses of two pinned mutable byte arrays (with compare) should not consume them.

from linear-base.

aspiwack avatar aspiwack commented on August 11, 2024

I'm being silent on this issue, because I need to think about it. Apologies.

from linear-base.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.