(.using [library [lux "*" ["_" test (.only Test)] [abstract [equivalence (.only Equivalence)] [monad (.only do)]] [control ["[0]" function]] [math ["[0]" random] [number ["n" nat]]]]] [\\library ["[0]" / (.only Functor)]]) (type: .public (Injection f) (All (_ a) (-> a (f a)))) (type: .public (Comparison f) (All (_ a) (-> (Equivalence a) (Equivalence (f a))))) (def: (identity injection comparison (open "@//[0]")) (All (_ f) (-> (Injection f) (Comparison f) (Functor f) Test)) (do [! random.monad] [sample (# ! each injection random.nat)] (_.property "Identity." ((comparison n.=) (@//each function.identity sample) sample)))) (def: (homomorphism injection comparison (open "@//[0]")) (All (_ f) (-> (Injection f) (Comparison f) (Functor f) Test)) (do [! random.monad] [sample random.nat increase (# ! each n.+ random.nat)] (_.property "Homomorphism." ((comparison n.=) (@//each increase (injection sample)) (injection (increase sample)))))) (def: (composition injection comparison (open "@//[0]")) (All (_ f) (-> (Injection f) (Comparison f) (Functor f) Test)) (do [! random.monad] [sample (# ! each injection random.nat) increase (# ! each n.+ random.nat) decrease (# ! each n.- random.nat)] (_.property "Composition." ((comparison n.=) (|> sample (@//each increase) (@//each decrease)) (|> sample (@//each (|>> increase decrease))))))) (def: .public (spec injection comparison functor) (All (_ f) (-> (Injection f) (Comparison f) (Functor f) Test)) (<| (_.for [/.Functor]) (all _.and (..identity injection comparison functor) (..homomorphism injection comparison functor) (..composition injection comparison functor) )))