-
Notifications
You must be signed in to change notification settings - Fork 20
Description
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) xsSo 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!