So with the caveat that I'm not super familiar with Validity...
The biggest thing that leaps out at me looking at it is that Hegel is very built around flexible user-specified data generation (using the library's base generators and combinators) mixed freely with test execution. Validity in contrast looks extremely type-based, which is convenient when you're only testing fairly general properties of built-in types, but I've never found flexible enough to be a really good basis for property-based testing once your testing needs get even a bit more complicated. e.g. a lot of tests want some sort of upper and lower bounds on their numbers, and I don't want to define a type for each.
For an only slightly more involved example of this, suppose you've got, say, a Project type, and Projects have an owner that is a User. You might want a test that is about a single user that has some number of projects. In a generator-based approach, this is easy: You just generate a User object, then you generate a bunch of Project objects that have to have that User as their owner. Just works.
In contrast, in a type based approach, there's basically no way to express this without e.g. defining a new ProjectsOwnedByASingleUser type and defining what it means to be a valid instance of that type... It's a lot of machinery for what is IMO a strictly worse user experience.
The biggest thing that leaps out at me looking at it is that Hegel is very built around flexible user-specified data generation (using the library's base generators and combinators) mixed freely with test execution. Validity in contrast looks extremely type-based, which is convenient when you're only testing fairly general properties of built-in types, but I've never found flexible enough to be a really good basis for property-based testing once your testing needs get even a bit more complicated. e.g. a lot of tests want some sort of upper and lower bounds on their numbers, and I don't want to define a type for each.
For an only slightly more involved example of this, suppose you've got, say, a Project type, and Projects have an owner that is a User. You might want a test that is about a single user that has some number of projects. In a generator-based approach, this is easy: You just generate a User object, then you generate a bunch of Project objects that have to have that User as their owner. Just works.
In contrast, in a type based approach, there's basically no way to express this without e.g. defining a new ProjectsOwnedByASingleUser type and defining what it means to be a valid instance of that type... It's a lot of machinery for what is IMO a strictly worse user experience.