5

Recently I saw a great video of Scott Wlaschin about patterns in functional programming. He gives an example of dividing a numbers. In f# we'd use int option for the result to handle division by zero in a nice functional way.

As another possibility he mentions creating a type that would not allow 0 as a valid value. Let's say IntsWithoutZero. How could we define this kind of type "functionally"?

I know how I'd do it with OO approach (e.g. write a IntsWithoutZero class and disallow 0 during construction).

2 Answers2

7

I would use a single case union type to wrap the integer.

I would put the type in its own module and access it through factory and getter methods like so:

    module IntsWithoutZero =
        // make the type constructor private
        type T = private IntsWithoutZero of int

        // factory that can apply the constraints
        let create value =
            // do check for zero here
            match value with
                | 0 -> None
                | _ -> IntsWithoutZero(value) |> Some

        // a method to extract the private data
        let value (IntsWithoutZero v) = v

    // ================== later in the code ==================
    // create the type
    let myInt = 5 |> IntsWithoutZero.create

    // ================== later when used ==================
    let myDividedValue =
        match myInt with
            | None -> None
            | Some(v) -> 
                // get value out
                let d = (v |> IntsWithoutZero.value)
                // do something zero cannot do
                Some(10 / d)

If you wanted to avoid option, alternatively you could throw an exception in the IntsWithoutZero.create method if the user supplied zero as a parameter.

Here is a blog post by Scott that does a much better job explaining this concept:

http://fsharpforfunandprofit.com/posts/designing-with-types-single-case-dus/

I hope this helps!

r31bs
  • 86
1

I know how I'd do it with OO approach (e.g. write a IntWihtoutZero class and disallow 0 during construction).

You do it the same way: hide the data constructor and only expose a function that checks if the integer is greater than 0.

Doval
  • 15,397