Skip to content

Equivalence a Type #44

@subttle

Description

@subttle

Hi, I think this project is really great, thank you for all the work you do on it!

I had an idea which I think is worth mentioning. Going with the description of "... for types where we know all the values" I think their is a good case for Finite a => Finite (Equivalence a) (the Equivalence a type being from http://hackage.haskell.org/package/contravariant-1.5/docs/Data-Functor-Contravariant.html#t:Equivalence). But I'm not sure if that is too specific for your library.

For the cardinality I think if you wanted to avoid computing universeF to get the length you could just compute the corresponding Bell number:
https://en.wikipedia.org/wiki/Equivalence_relation#Counting_possible_partitions

To actually generate the list of partitions I've been using:

-- partitions of a set
-- partitions {0..2} = [ [[0],[1],[2]]
--                     , [[0],[2,1]]
--                     , [[2,0],[1]]
--                     , [[1,0],[2]]
--                     , [[2,1,0]]
--                     ]
partitions  (Foldable t)  t a  [[NonEmpty a]]
partitions = Foldable.foldl (\xs  (xs >>=) . go) [[]]
   where go  a  [NonEmpty a]  [[NonEmpty a]]
         go x []       = [[ x :| [] ]]
         go x (y : ys) = fmap (y :) (go x ys) <> [(x :| NE.toList y) : ys]

And then just in case you are interested here are the helper functions:

-- for each list (which represents an equivalence class), check if both a₁ and a₂ are in it
-- if for any list two are in the same list return true, otherwise false
toEquivalence  (Finite a, Foldable t)  t (NonEmpty a)  Equivalence a
toEquivalence parts = Equivalence (\a₁ a₂  any (\xs  (a₁ `elem` xs) && (a₂ `elem` xs)) parts)

fromEquivalence   a . (Finite a)  Equivalence a  [NonEmpty a]
fromEquivalence (Equivalence r) = unfoldr go universeF
      where go  [a]  Maybe (NonEmpty a, [a])
            go []       = Nothing
            go (x : xs) = Just (x :| p, np)
                    where (p, np) = List.partition (r x) xs

So then for the Finite instance, you would potentially be able to do something like:

  universeF  [Equivalence a]
  universeF = fmap toEquivalence (partitions universeF)

Fair warning, I haven't written any of this with performance in mind, but I still think the idea is worth mentioning. If you don't see a use for it please close the ticket I would not take offense!

Have a nice day!

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions