1
import SwiftCheck
2
import Bow
3
import BowGenerators
4

5
public class FoldableLaws<F: Foldable & EquatableK & ArbitraryK> {
6 1
    public static func check() {
7 1
        leftFoldConsistentWithFoldMap()
8 1
        rightFoldConsistentWithFoldMap()
9 1
        existsConsistentWithFind()
10 1
        existsIsLazy()
11 1
        forAllIsLazy()
12 1
        forallConsistentWithExists()
13 1
        forallReturnsTrueIfEmpty()
14 1
        foldMIdIsFoldL()
15
    }
16
    
17 1
    private static func leftFoldConsistentWithFoldMap() {
18 1
        property("Left fold consistent with foldMap") <~ forAll { (input: KindOf<F, Int>, f: ArrowOf<Int, Int>) in
19 1
            return F.foldMap(input.value, f.getArrow) == F.foldLeft(input.value, Int.empty(), { b, a in b.combine(f.getArrow(a)) })
20
        }
21
    }
22
    
23 1
    private static func rightFoldConsistentWithFoldMap() {
24 1
        property("Right fold consistent with folMap") <~ forAll { (f: ArrowOf<Int, Int>, fa: KindOf<F, Int>) in
25 1
            return fa.value.foldMap(f.getArrow) ==
26 1
                fa.value.foldRight(Eval.later { Int.empty() }, { a, lb in lb.map { b in f.getArrow(a).combine(b) }^ }).value()
27
        }
28
    }
29
    
30 1
    private static func existsConsistentWithFind() {
31 1
        property("Exists consistent with find") <~ forAll { (input: KindOf<F, Int>, predicate: ArrowOf<Int, Bool>) in
32 1
            return F.exists(input.value, predicate.getArrow) == F.find(input.value, predicate.getArrow).fold(constant(false), constant(true))
33
        }
34
    }
35
    
36 1
    private static func existsIsLazy() {
37 1
        property("Exists is lazy") <~ forAll { (fa: KindOf<F, Int>) in
38 1
            var x = 0
39 1
            let _ = fa.value.exists { _ in x += 1; return true }
40 1
            let expected = fa.value.isEmpty ? 0 : 1
41 1
            return x == expected
42
        }
43
    }
44
    
45 1
    private static func forAllIsLazy() {
46 1
        property("ForAll is lazy") <~ forAll { (fa: KindOf<F, Int>) in
47 1
            var x = 0
48 1
            let _ = fa.value.forall { _ in x += 1; return true }
49 1
            let expected = fa.value.isEmpty ? 0 : fa.value.count
50 1
            return x == expected
51
        }
52
    }
53
    
54 1
    private static func forallConsistentWithExists() {
55 1
        property("Forall consistent with exists") <~ forAll { (input: KindOf<F, Int>, predicate: ArrowOf<Int, Bool>) in
56 1
            if F.forall(input.value, predicate.getArrow) {
57 1
                let negationExists = F.exists(input.value, predicate.getArrow >>> not)
58 1
                return !negationExists && (F.isEmpty(input.value) || F.exists(input.value, predicate.getArrow))
59 1
            } else {
60 1
                return true
61
            }
62
        }
63
    }
64
    
65 1
    private static func forallReturnsTrueIfEmpty() {
66 1
        property("Forall returns true if empty") <~ forAll { (input: KindOf<F, Int>, predicate: ArrowOf<Int, Bool>) in
67 1
            return !F.isEmpty(input.value) || F.forall(input.value, predicate.getArrow)
68
        }
69
    }
70
    
71 1
    private static func foldMIdIsFoldL()  {
72 1
        property("Exists consistent with find") <~ forAll { (input: KindOf<F, Int>, f: ArrowOf<Int, Int>) in
73 1
            let foldL = F.foldLeft(input.value, Int.empty(), { b, a in b.combine(f.getArrow(a)) })
74 1
            let foldM = Id.fix(F.foldM(input.value, Int.empty(), { b, a in Id(b.combine(f.getArrow(a))) })).value
75 1
            return foldL == foldM
76
        }
77
    }
78
}

Read our documentation on viewing source code .

Loading