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!
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)(theEquivalence atype 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
cardinalityI think if you wanted to avoid computinguniverseFto 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:
And then just in case you are interested here are the helper functions:
So then for the
Finiteinstance, you would potentially be able to do something like: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!