Extending Core.Option module in F# - 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

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.

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

Does it help if you add the AutoOpen attribute to the module?
[<AutoOpen>]
module Microsoft.FSharp.Core.Option
let filter predicate op =
match op with
| Some(v) -> if predicate(v) then Some(v) else None
| None -> None
EDIT
This works, but only across assembly borders. It doesn't work within the same assembly:
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
[<assembly:AutoOpen("Microsoft.FSharp.Core")>]
do ()
To call it from another assembly:
[<EntryPoint>]
let main args =
let f () = Some "" |> Option.filter (fun f -> true)
Console.WriteLine("Hello world!")
0

According to the docs something like this should work in extending a type. However I must have got something wrong as it won't compile and gives. the following error:
One or more of the declared type parameters for this type extension
have a missing or wrong type constraint not matching the original type
constraints on 'Option<_>'F# Compiler(957)
open System.Runtime.CompilerServices
[<Extension>]
type Option with
[<Extension>]
static member fromBool predicate word =
if predicate word
then Some word
else None
This isn't a functioning answer more an addendum to the original question. Not sure if it is worth opening a new thread?

Related

final output of Result, in F#

This seems like a question that has an ultra simple answer, but I can't think of it:
Is there a built in method, within Result, for:
let (a: Result<'a, 'a>) = ...
match a with
| Ok x -> x
| Error e -> e
No, because this function requires the Ok type and the Error type to be the same, which makes Result less general.
No, there isn't any function which will allow you to do so. But you can easily define it:
[<RequireQualifiedAccess>]
module Result =
let join (value: Result<'a, 'a>) =
match value with
| Ok v -> v
| Error e -> e
let getResult s =
if System.String.IsNullOrEmpty s then
Error s
else
Ok s
let a =
getResult "asd"
|> Result.join
|> printfn "%s"
It doesn't make Result less general (as said by #brianberns), because it's not an instance member. Existence of Unwrap doesn't make Task less general
Update
After more scrupulous searching inside FSharpPlus and FSharpx.Extras I've found necessary function. It's signature ('a -> 'c) -> ('b -> 'c) -> Result<'a,'b> -> c instead of Result<'a, 'a> -> 'a and it's called Result.either in both libraries (source 1 and source 2). So in order to get value we may pass id as both parameters:
#r "nuget:FSharpPlus"
open FSharpPlus
// OR
#r "nuget:FSharpx.Extras"
open FSharpx
getResult "asd"
|> Result.either id id
|> printfn "%s"
Also it's may be useful to define shortcut and call it Result.join or Result.fromEither as it's called in Haskell

Prevent shadowing of Ok and Error with FParsec?

Suppose I have a test like this:
module MyTests
open Xunit
open FParsec
open FsUnit.Xunit
open MyParsers
[<Fact>]
let ``pfoo works as expected`` () =
let text = "blahblahblah"
let actual =
match run pfoo text with
| Success (x, _, _) -> Result.Ok x
| Failure (s, _, _) -> Result.Error s
let expected : Result<Foo, string> =
Result.Ok
{
Foo = "blahblahblah"
}
expected
|> should equal actual
open FParsec will shadow Ok so that I need to fully qualify it like Result.Ok.
This is pretty annoying. Is there a good way to "open" Result again so that I can write Ok unqualified?
It's not Result that you need to "open", but Microsoft.FSharp.Core, which is the module in which Result and both its constructors are defined. This module is open by default, but you can open it again to have its definitions closer in the scope:
open Xunit
open FParsec
open FsUnit.Xunit
open MyParsers
open Microsoft.FSharp.Core
Alternatively, you can alias just the Ok identifier:
let Ok = Result.Ok
let x = Ok "foo" // x : Result<string, _>
I prefer this latter method, because it minimizes the impact surface and thus reduces the chance of unexpected surprises.
The downside is that the aliased Ok won't work for pattern matching:
match x with
| Ok y -> ... // This is Ok from FParsec
If you need pattern matching as well, you'll have to alias the matcher too:
let (|Ok|Error|) x = match x with | Result.Ok o -> Ok o | Result.Error e -> Error e
At which point I would probably fall back to reopening the module.

F# - Get list of methods in module

I have module like this
module CommonModule
let addFive x =
x+5
let multiFive x =
x*5
And I would like to list methods of this module by reflection.
I found this: Can you list the contents of a namespace or module in F#, but I don't know how to use it.
I'm new in F#.
Please help
I think the only way to do this is to declare a type inside the module, then use reflection to get the DeclaringType and call GetMethods on that:
open System.Reflection
module CommonModule =
type Marker = interface end
let f x = x * x
typeof<CommonModule.Marker>.DeclaringType.GetMethods()
This will give you a MethodInfo [] containing f and the methods inherited from System.Object:
[|Int32 f(Int32); System.String ToString(); Boolean Equals(System.Object);
Int32 GetHashCode(); System.Type GetType()|]
EDIT (responding to lukaszb's comment)
If you want to look up the module by name, you'll need to get the assembly first, then find the module type within the assembly and call GetMethods. To do this for the previous example, you would add the following code:
// Get the assembly somehow (by name, by GetEntryAssembly, etc)
let assembly = Assembly.GetExecutingAssembly()
// Retrieve the methods (including F# functions) on the module type
let functions =
match assembly.GetTypes() |> Array.tryFind (fun t -> t.Name = "CommonModule") with
| Some moduleType -> moduleType.GetMethods()
| None -> [||]
// Find the function you want
match functions |> Array.tryFind (fun f -> f.Name = "f") with
| Some f -> f.Invoke(null, [|2|]) // Invoke the function
| None -> failwith "Function `f` not found"
One benefit of doing it this way is that you no longer need the Marker type in the module.

System.Linq.Enumerable.OfType<T> - is there a F# way?

I'm looking to use the F# WSDL Type Provider. To call the web service I am using, I need to attach my client credentials to the System.ServiceModel.Description.ClientCredentials.
This is the C# code I have:
var serviceClient = new InvestmentServiceV1Client.InvestmentServiceV1Client();
foreach (ClientCredentials behaviour in serviceClient.Endpoint.Behaviors.OfType<ClientCredentials>())
{
(behaviour).UserName.UserName = USERNAME;
(behaviour).UserName.Password = PASSWORD;
break;
}
This is the F# code I have so far:
let client = new service.ServiceTypes.InvestmentServiceV1Client()
let xxx = client.Endpoint.Behaviors
|> Seq.choose (fun p ->
match box p with
:? System.ServiceModel.Description.ClientCredentials as x -> Some(x)
_ -> None)
|> (System.ServiceModel.Description.ClientCredentials)p.UserName.UserName = USERNAME
Is there an F# equivalent of System.Linq.Enumerable.OfType<T> or should I just use raw OfType<T> ?
I suppose the question is mainly about the break construct, which is not available in F#. Well, the code really just sets the user name and password for the first element of the collection (or none, if the collection is empty). This can be done easily using pattern matching, if you turn the collection to an F# list:
// Get behaviours as in C# and convert them to list using 'List.ofSeq'
let sc = new InvestmentServiceV1Client.InvestmentServiceV1Client()
let behaviours = sc.Endpoint.Behaviors.OfType<ClientCredentials>() |> List.ofSeq
// Now we can use pattern matching to see if there is something in the list
match behaviours with
| behaviour::_ ->
// And if the list is non-empty, set the user name and password
behaviour.UserName.UserName <- USERNAME
behaviour.UserName.Password <- PASSWORD
| _ -> ()
I think you've already implemented the F# equivalent of .OfType(). For emulating the break statement you can do as Tomas does in his answer (matching on list), or you call Seq.head (throws if there are no elements left), or you can do this:
let xxx =
client.Endpoint.Behaviors
|> Seq.choose (function
| :? System.ServiceModel.Description.ClientCredentials as x -> Some x
| _ -> None )
|> Seq.tryPick Some
match xxx with
| Some behavior -> ... // First element of required type found
| None -> ... // No elements of required type at all in sequence

Seq and IQueryable in F#

I am reading Web cloud and mobile solution with F# and I try to follow the web site the author is building. But I have some problem, I am unable to solve. I understand the logic of what I am doing , but it looks like some piece of code is missing to make it work .I have read up to page 19.
I have the following repository module :
module Repository =
let get (source : IQueryable<_>) queryFn=
queryFn |> Seq.toList
let getAll ()=
fun s -> query { for x in s do
select x }
The idea is to use getAll in queryFn to get all items from source. But I have a cast problem between the two .
Here is the controller that makes use of it:
[<HandleError>]
type GuitarsController(context : IDisposable, ?repository ) =
inherit Controller()
let fromRepository =
match repository with
| Some v -> v
| _ -> (context :?> FsMvcAppEntities).guitars
|> Repository.get
new() = new GuitarsController(new FsMvcAppEntities())
member this.Index() =
getAll()
|> fromRepository
|> this.View
getAll() does not go well with |> fromRepository.
The type ''b -> Linq.IQueryable<'c>' is not compatible with the type
'seq<'a>'.
When looking at the type defined in the repository module I can see that queryFn is :
val get : source:IQueryable<'a> -> queryFn:seq<'b> -> 'b list
and the getall gives
unit -> s:System.Linq.IQueryable<'a> -> System.Linq.IQueryable<'a>
Your Repository.get makes no use of source :D.
Change it to:
module Repository =
let get (source : IQueryable<_>) queryFn =
queryFn source |> Seq.toList

Resources