
On Mon, Oct 07, 2024 at 05:38:30PM -0400, Benjamin Redelings wrote:
I'm new to Haskell, and I'm writing a class for evolutionary trees. Since I'm new to Haskell, trying to encode information at the type level is new to me. In C++ I'd use runtime checks to ask whether (for example) a tree is rooted. Or I'd have the getRoot function return Maybe NodeID and then make the methods for checking if a branch points rootward throw an exception if the tree is unrooted.
I think I'd just do data AugmentedTree roots lengths labels = MkAugmentedTree { tree :: Tree, labels :: labels, roots :: roots, lengths :: lenghts } and then just do stuff like type FullyAugmentedTree = AugmentedTree [NodeId] (IntMap Double) (IntMap (Maybe l)) type PartiallyAugmentedTree = AugmentedTree [NodeId] () (IntMap (Maybe l)) For rootedness-independence I strongly recommend against any type class shenanigans. Instead you can do data PossiblyRootedTree lengths labels where RootedTree :: AugmentedTree [NodeId] lengths labels UnrootedTree :: AugmentedTree () lengths labels and then isRooted :: PossiblyRootedTree lengths labels -> Bool isRooted = \case RootedTree {} -> True UnrootedTree {} -> False (but `isRooted` is not really very useful compared to just pattern matching every where you need to know.) Tom