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
Related
I have a function that returns Task<bool> (C#).
Task<bool> Update(MemberMarketUpdate memberMarketUpdate);
I'm trying to mock it using Moq (F#).
let verifyUpdate(update:MemberMarketUpdate) =
update.Id |> should equal "market id"
let setup = associationRepository.Setup (fun r -> r.Update(It.IsAny<MemberMarketUpdate>() ))
setup.Callback(fun update -> verifyUpdate update) |> ignore
//setup.Returns(Task.FromResult(True)) <- does not compile
//setup.ReturnsAsync(True) <- does not compile
I'm not able to use ReturnsAsync(True) to mock the Task<bool> result.
The error says:
No overloads match for method ReturnsAsync. The available overloads
are shown below.
(35 overloads here)
What is the correct syntax?
I tried to get your code to type check in a simple F# script file and the only thing I had to do to make it work was to change your upper-case True to lower-case true.
My complete script that type-checks fine, including all the necessary definitions and references looks like this:
#r #"packages\Moq\lib\net45\Moq.dll"
#r #"packages\NUnit\lib\net45\nunit.framework.dll"
#r #"packages\FsUnit\lib\net46\FsUnit.NUnit.dll"
#r #"packages\System.Threading.Tasks.Extensions\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll"
open Moq
open FsUnit
open System.Threading.Tasks
type MemberMarketUpdate =
{ Id: string }
type IAssociationRepository =
abstract Update : MemberMarketUpdate -> Task<bool>
let verifyUpdate(update:MemberMarketUpdate) =
update.Id |> should equal "market id"
let associationRepository = new Mock<IAssociationRepository>();
let setup = associationRepository.Setup (fun r -> r.Update(It.IsAny<MemberMarketUpdate>() ))
setup.Callback(fun update -> verifyUpdate update) |> ignore
setup.Returns(Task.FromResult(true))
setup.ReturnsAsync(true)
I am not that familiar with f# but try it all in one fluent call like the following, if possible.
associationRepository
.Setup(fun r -> r.Update(It.IsAny<MemberMarketUpdate>()))
.Callback(fun update -> verifyUpdate update)
.ReturnsAsync(True) |> ignore
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.
I have created a ListTypeConverter:
type ListTypeConverter<'source, 'destination>() =
interface ITypeConverter<'source list, Proxies.List> with
member this.Convert(source, destination, context) =
let proxyList = new Proxies.List()
source
|> List.map(fun item -> _mapper.Map<'source, 'destination>(item))
|> List.iter(fun item -> proxyList.addEnd(item) |> ignore)
proxyList
And usage: ForMemberFs by Ian Griffiths
this.CreateMap<SourceItemType list, Proxies.List>().ConvertUsing<ListTypeConverter<SourceItemType, DestItemType>>()
this.CreateMap<SourceType, DestType>().
ForMemberFs((fun d -> d.MyNonGenericList), (fun opts -> opts.MapFrom(fun s -> s.MyGenericList))).
This works fine if I only have one property on my primary map that maps from a 'a list -> Proxy.List. But the moment I introduce a second mapping from a 'b -> Proxy.List then I get an InvalidCastException.
Introducing a second mapping causes the exception:
this.CreateMap<SourceItemType list, Proxies.List>().ConvertUsing<ListTypeConverter<SourceItemType, DestItemType>>()
this.CreateMap<SourceItemType2 list, Proxies.List>().ConvertUsing<ListTypeConverter<SourceItemType2, DestItemType2>>()
this.CreateMap<SourceType, DestType>().
ForMemberFs((fun d -> d.MyNonGenericList), (fun opts -> opts.MapFrom(fun s -> s.MyGenericList))).
ForMemberFs((fun d -> d.MyNonGenericList2), (fun opts -> opts.MapFrom(fun s -> s.MyGenericList2))).
Exception:
Unable to cast object of type 'obj' to type 'DestItemType'
So, my problem is a bit deeper than just F# and AutoMapper. The Proxies.List type is actually gotten via a TypeProvider for Microsoft Dynamics AX that we've written in-house. I wanted to exclude that variable from the equation, so I wrote a simple script using System.Collections.Generic.List<'t> -> System.Collections.ArrayList (which is non-generic) and I was able to successfully cast from items in my ArrayList back to their correct "destination" type.
While I'm here, we came up with some pretty cool F# helpers for AutoMapper:
type OptionExpressions =
static member MapFrom<'source, 'destination, 'sourceMember, 'destinationMember> (e: 'source -> 'sourceMember) =
System.Action<IMemberConfigurationExpression<'source, 'destination, 'destinationMember>> (fun (opts: IMemberConfigurationExpression<'source, 'destination, 'destinationMember>) -> opts.MapFrom(e))
static member UseValue<'source, 'destination, 'value> (e: 'value) =
System.Action<IMemberConfigurationExpression<'source, 'destination, 'value>> (fun (opts: IMemberConfigurationExpression<'source, 'destination, 'value>) -> opts.UseValue(e))
static member Ignore<'source, 'destination, 'destinationMember> () =
System.Action<IMemberConfigurationExpression<'source, 'destination, 'destinationMember>> (fun (opts: IMemberConfigurationExpression<'source, 'destination, 'destinationMember>) -> opts.Ignore())
Usage:
// Shortened local helpers
let mapFrom = OptionExpressions.MapFrom
let ignoreMap = OptionExpressions.Ignore
let useValue = OptionExpressions.UseValue
this.CreateMap<Source, Destination>()
.ForMemberFs((fun d -> d.DestMember1), mapFrom (fun s -> s.SourceMember1))
.ForMemberFs((fun d -> d.DestMember2), useValue (MyValue))
.ForMemberFs((fun d -> d.DestMember3), ignoreMap ())
I'd let to mock an IBus with Foq.
One of the methods on the IBus is OpenPublishChannel, which returns an IPublishChannel. IPublishChannel in turn has a Bus property that returns the parent IBus.
My current code is below, but obviously it doesn't compile as mockBus is not defined by the point I need it. Is there a way of setting up recursive mocking like this without creating two mocks of either interface?
open System
open EasyNetQ
open Foq
let mockChannel =
Mock<IPublishChannel>()
.Setup(fun x -> <# x.Bus #>).Returns(mockBus)
.Create()
let mockBus =
Mock<IBus>()
.Setup(fun x -> <# x.OpenPublishChannel() #>).Returns(mockChannel)
.Create()
Foq supports a Returns : unit -> 'TValue method so you can lazily create a value.
Using a little mutation instances can refer to each other:
type IPublishChannel =
abstract Bus : IBus
and IBus =
abstract OpenPublishChannel : unit -> IPublishChannel
let mutable mockBus : IBus option = None
let mutable mockChannel : IPublishChannel option = None
mockChannel <-
Mock<IPublishChannel>()
.Setup(fun x -> <# x.Bus #>).Returns(fun () -> mockBus.Value)
.Create()
|> Some
mockBus <-
Mock<IBus>()
.Setup(fun x -> <# x.OpenPublishChannel() #>).Returns(fun () -> mockChannel.Value)
.Create()
|> Some
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?