-- | @splitProp@ returns a list whose length is one or more.
--
-- prop> \ p -> not . null $ splitProp p
-- prop> \ t -> let p = Prop t in splitProp p == [([], p)]
--
-- prop> \ s t u -> let [p,q,r] = map Prop [s,t,u] in splitProp (p ~> q ~> r) == [([], p ~> q ~> r), ([p], q ~> r), ([p, q], r)]
-- prop> \ t ts -> let ps = map Prop (t:ts) in length (splitProp (foldr1 (~>) ps)) == length ps
splitProp :: Prop -> [([Prop], Prop)]
splitProp = nub . f where
    f p@(Prop _) = [([], p)]
    f r@(Arrow p q) = ([], r) : ([p], q) : map (mapFst (p :)) (f q)

-- | prop> \ p -> not . null $ conclusions p
splitProp :: Prop -> [([Prop], Prop)]
splitProp = nub . f where
    f p@(Prop _) = [([], p)]
    f r@(Arrow p q) = ([], r) : ([p], q) : map (mapFst (p :)) (f q)

-- | prop> \ p -> not . null $ conclusions p
splitProp = nub . f where
    f p@(Prop _) = [([], p)]
    f r@(Arrow p q) = ([], r) : ([p], q) : map (mapFst (p :)) (f q)

-- | prop> \ p -> not . null $ conclusions p