Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Representing a restricted type without using a class

Tags:

.net

f#

f#-4.0

In F# can I represent a restricted type without defining a class? Lets say I want to represent all the pairs of number where the first divides the second.

in C# I could do:

class PairDivides
{
    int a {get;private set;}
    int b {get;private set;}

    PairDivides(int first, int second)
    {
        if (a % b != 0)
        {
            throw new Exception();
        }

        this.a = first;
        this.b = second;
    }
}

Now it's impossible to create a PairDivides instance where b doesn't divide a...

Can this be done in F# using only the functional constructs (record, discriminated union, maybe active patterns, etc.)?

I want to be able to create and receive something like these pairs being certain that they are constructed correctly.

like image 239
AK_ Avatar asked Jan 13 '16 19:01

AK_


People also ask

What does encapsulation mean in Java?

Encapsulation in Java is the process by which data (variables) and the code that acts upon them (methods) are integrated as a single unit. By encapsulating a class's variables, other classes cannot access them, and only the methods of the class can access them.

How do I restrict a generic type in Java?

Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class.

How can we restrict to create limited object of any class?

Create INSTANCE of same class by instantiating class & this INSTANCE should be with private & static modifier. Provide public static method that returns same INSTANCE of class every time. Finally, create private constructor so that no-one create object from outside of class.


1 Answers

You can do this by making the type private. The only downside is that you then need to provide functions to access the data:

module Pairs =
    type PairDivides = private { a: int; b: int }

    let createPairDivides a b =
        match a % b with
        | 0 -> Some { PairDivides.a = a ; b = b }
        | _ -> None

    let print div =
        printfn "{%d %d}" div.a div.b

    let tryPrint div =
        match div with
        | Some a -> print a
        | None -> printfn "None"

let a = Pairs.createPairDivides 2 2

let b = a.Value

// This is inaccessible: b.a

Pairs.createPairDivides 2 2 |> Pairs.tryPrint
Pairs.createPairDivides 2 3 |> Pairs.tryPrint

By providing a function to create the pair, and functions to use or extract from it as necessary, you completely eliminate the ability to create invalid pairs (you'll get None back instead of a bad pair) without using exceptions.

The disadvantage is you need to provide mechanisms to extract the values from the pairs, as the type is now inaccessible when used outside of your current module.

That being said, there's nothing wrong with doing this via classes either. You can get the same level of enforcement via creating a class, if you prefer:

type PairDivides private (a,b) =
    member __.A = a
    member __.B = b

    static member Create a b =
        match a % b with
        | 0 -> Some(PairDivides(a,b))
        | _ -> None


PairDivides.Create 2 2 |> printfn "%A"
PairDivides.Create 2 3 |> printfn "%A"
like image 96
Reed Copsey Avatar answered Nov 15 '22 03:11

Reed Copsey