Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending Core.Option module in F#

Tags:

f#

I want to extend one of the existing "core" modules, like Core.Option:

module Microsoft.FSharp.Core.Option

    let filter predicate op =
        match op with
        | Some(v) -> if predicate(v) then Some(v) else None
        | None -> None

(I know about bind function, but I think filter method for options in some case is more convenient).

But unfortunetely I can't use filter method without explicitely open Microsoft.FSharp.Core namespace:

// Commenting following line will break the code!
open Microsoft.FSharp.Core

let v1 = Some 42
let v2 = v1 |> Option.filter (fun v -> v > 40)

printfn "v2 is: %A" v2

In most cases we can't use functions from module without opening appropriate namespace. F# compiler "opens" some predefine (core) namespace automatically (like Microsoft.FSharp.Core), this will not bring into the scope methods from "module extensions" and we still should open core namespaces manually.

My question is: Is there any workarounds?

Or the best way to extend "core" modules is to create such extensions in custom namespace and open this namespace manually?

// Lets custom Option module in our custom namespace
module CustomNamespace.Option

    let filter predicate op = ...

// On the client side lets open our custom namespace.
// After that we can use both Option modules simultaneously!
open CustomNamespace

let v1 = Some 42
let b = 
    v1 |> Option.filter (fun v -> v > 40) // using CustomNamespace.Option
    |> Option.isSome // using Microsoft.FSharp.Core.Option
like image 446
Sergey Teplyakov Avatar asked Apr 18 '13 08:04

Sergey Teplyakov


2 Answers

For production code I would do what the Taha's answer suggests: create your own module and open/alias it as necessary. Most of your life as programmer will be spent reading code. It can be quite frustrating reading F# code where it is not clear where methods come from.

That being said, I was surprised to find that this works:

namespace Microsoft.FSharp.Core

module Option =

    let filter predicate op =
        match op with
        | Some(v) -> if predicate(v) then Some(v) else None
        | None -> None

namespace USERCODE

module Option = Microsoft.FSharp.Core.Option

module M =

    let test () =
        Some 1
        |> Option.filter (fun x -> x > 0)
        |> Option.map (fun x -> x + 1)

It does not remove the need to write something in the head of your files, but it does work around needing to open a namespace. Not relevant for Microsoft.FSharp.Core as it is always open by default, but helpful for other namespaces.

like image 184
t0yv0 Avatar answered Oct 21 '22 09:10

t0yv0


In order to extend an F# module create another with the same name:

module Option =

    let filter predicate op =
        match op with
        | Some v  -> match predicate v with true -> Some v | false -> None
        | None    -> None


let v1 = Some 42
let v2 = v1 |> Option.filter (fun v -> v > 40)

printfn "v2 is: %A" v2
like image 21
Taha Avatar answered Oct 21 '22 09:10

Taha