1

How can I interpret property based test code?

I'm struggling to translate the instructions on the following snippet:

let myProperty = Prop.forAll fiveAndThrees <| fun number ->

    let actual = transform number

    let expected = "jbdhjsdhjdsjhsdglsdjlljh"
    expected = actual

Check.QuickThrowOnFailure myProperty

Specifically, I'm struggling with the backwards pipeline operator (i.e. "<|").

Here's the test:

[<Fact>]
let ``FizzBuzz.transform returns FizzBuzz`` () =
    let fiveAndThrees = Arb.generate<int> |> Gen.map ((*) (3 * 5)) 
                                          |> Arb.fromGen

    let myProperty = Prop.forAll fiveAndThrees <| fun number ->

        let actual = transform number

        let expected = "jbdhjsdhjdsjhsdglsdjlljh"
        expected = actual

    Check.QuickThrowOnFailure myProperty

Can someone please guide me step by step on how this code works?

Could this be rewritten using the forward pipe operator (i.e. "|>")?

Scott Nimrod
  • 11,206
  • 11
  • 54
  • 118

1 Answers1

3

This answer only covers why <| is used instead of |>.

Here are 5 examples that work toward making use of <| with a large function. The 6th example is to show how the code looks using |> instead of <|. The point is that with the 6th example using |> you have to look into the code to find the primary function funThatNeedsListAndFunc but with <| the primary function funThatNeedsListAndFunc is obvious. So you typically see <| when the last parameter is a function and you want to pass in the function after the primary function for easier comprehension. That's all; don't read more into than that.

After reading the Mark's blog I also learned that <| is useful to remove ( ) around fun. An example using ( ) is given as example 7.

let funThatNeedsListAndFunc list func =
    func list

let func = List.sum
let list = Seq.toList { 0 .. 5}

let result1 = funThatNeedsListAndFunc list func

printfn "result1: %A" result1

let result2 = funThatNeedsListAndFunc list <| func

printfn "result2: %A" result2

let result3 = funThatNeedsListAndFunc list <| List.sum

printfn "result3: %A" result3

let result4 = funThatNeedsListAndFunc list <| 
    fun (list : 'a list) -> List.sum list

printfn "result4: %A" result4

let result5 = funThatNeedsListAndFunc list <| 
    fun (list : 'a list) -> 
        // This will be a long function
        let a = 1
        let b = 2
        let c = a * b
        let result = List.sum list
        let d = "more useless lines"
        let (e,f,g) = ("a", 15, 3.0)
        result

printfn "result5: %A" result5

.

let result6 = 
    fun (list : 'a list) -> 
        // This will be a long function
        let a = 1
        let b = 2
        let c = a * b
        let result = List.sum list
        let d = "more useless lines"
        let (e,f,g) = ("a", 15, 3.0)
        result
    |> funThatNeedsListAndFunc list

printfn "result6: %A" result6

.

let result7 = 
    funThatNeedsListAndFunc list (fun (list : 'a list) -> 
        // This will be a long function
        let a = 1
        let b = 2
        let c = a * b
        let result = List.sum list
        let d = "more useless lines"
        let (e,f,g) = ("a", 15, 3.0)
        result)

printfn "result7: %A" result7
Guy Coder
  • 24,501
  • 8
  • 71
  • 136
  • After reading the blog entry by Mark, I see that one can also use it to help when formatting. Didn't know that one. Like I noted before, some of the best F# programmers also know Haskell. – Guy Coder May 12 '16 at 14:17
  • Are you suggesting that I learn Haskell before gaining expertise in F#? – Scott Nimrod May 12 '16 at 14:21
  • No not before, but maybe in parallel. If you read the blog by Mark you will see that he notes he learned about using `<|` from Haskell. I still need to take the Haskell plunge, but as you noted I tend to focus on the math/logic side and so work more with type theory and higher order logic. – Guy Coder May 12 '16 at 14:29
  • This does not mean that I see programming as being based on math, but that their are ideas that work together. See: [How are programming languages and foundations of mathematics related?](http://cs.stackexchange.com/questions/9756/how-are-programming-languages-and-foundations-of-mathematics-related) That might be most useful answer I have ever received from StackExchange sites and explains why one should study Haskell. – Guy Coder May 12 '16 at 14:30
  • Haskell in particular *is* maths, though. – TeaDrivenDev May 12 '16 at 14:47
  • @TeaDrivenDev I would ask you why as an SO question but that would be a subjective question. Why do you say `Haskell in particular is maths`? I am not agreeing or disagreeing with you but want to understand your reasoning. – Guy Coder May 12 '16 at 14:53
  • @GuyCoder The strictness with which Haskell demands things to be done is very mathematical, i.e. requiring everything to be strictly composed of expressions vs. F# allowing for loosening things up with possibilities like intermittent `let` bindings. (There may also have been some snark in my comment, as my short brush with Haskell was not very joyful.) – TeaDrivenDev May 13 '16 at 02:01
  • @ScottNimrod Another reason I keep dropping Haskell hints is that when programming you are in a world of chaos, as in chaos theory, and there are [strange attractors](https://en.wikipedia.org/wiki/Chaos_theory#Strange_attractors) pulling you toward programming types, e.g. OO, functional, logical, etc. and I see you being pulled between OO and functional, but if you start looking at Haskell, you will have another attractor that will pull you more toward the functional way of thinking. – Guy Coder May 13 '16 at 11:08