Error/Either monads are the perfect middle ground IMHO. You get errors as data types and an efficient way to abstract away the boilerplate associated with it.
469 karma · joined September 14, 2017
But Haskell's quickCheck doesn't seem to find a problem.
λ quickCheck @(Float -> Bool) $ \x -> 2 * x == x + x
+++ OK, passed 100 tests.
λ quickCheck @(Double -> Bool) $ \x -> 2 * x == x + x
+++ OK, passed 100 tests.
It doesn't like associativity though. λ quickCheck @(Double -> _) $ \a b c ->
(a + b) + c == a + (b + c)
*** Failed! Falsifiable (after 6 tests and 4 shrinks):
20.0
3.5741489348898856
2.894651135185324In Coq for instance.
Axiom functional_extensionality: forall {X Y: Type} {f g : X -> Y},
(forall (x: X), f x = g x) -> f = g.
Theorem x2_eq_xplus:
(fun x => 2 * x) = (fun x => x + x).
Proof.
apply functional_extensionality. intros.
destruct x.
- reflexivity.
- simpl. rewrite <- plus_n_O. reflexivity.
Qed.