Is it possible to create methods or stand-alone functions in a computation expression that can later be used by one of the canonical methods of a computation expression?
I want something like this:
type FormletBuilder(ctx : HttpContext) =
let get_int =
match Int32.TryParse (ctx.Request.["foo"]) with
| (true, n) -> Some n
| _ -> None
//similar definitions for get_date, get_non_empty_str, etc...
member x.Bind (read : 'a option, f : 'a -> option 'a) =
match read with
| Some x -> f(x)
| None -> None
member x.Return (obj) = Some obj
member x.Zero () = None
let person = formlet ctx {
let! id = get_int "id"
let! name = get_non_empty_str "fullname"
return Person(id, name)
}
But the compiler complains that get_int is not defined.
let bindings in class definitions are always private. You can define a member instead.
For an easy solution, you could do:
let formlet = FormletBuilder(ctx)
let person = formlet {
let! id = formlet.get_int "id"
...
}
I understand now that what you actually want is a maybe monad, and the workflow argument is there just to make use of some syntactic sugar? If so, there are a couple other things you can consider doing:
Go Haskell on it all the way and implement a MaybeReader monad, so that both the maybe and the reader parts of it are explicit in type,
Put the sugar away - I understand you don't actually need the context in any core builder members? If so, than maybe it had no business being an argument to the builder in the first place. Have a 'clean' maybe monad, move get_int etc. into a proper module and have them take HttpContext explicitly as an argument.
If you're using F# 3.0 or later, you can define get_int etc. as custom operations of the workflow, which should effectively give you the nice syntax you want to have. Here's a good post about it by Tomas Petricek.
Combine 2. and 3. - instead of a large number of custom operations, have one - ask - which will take an HttpContext -> 'a function and apply ctx to it. Effectively a bastardized version of reader. Then you can move your get_int etc. into a proper module.
Related
I have been doing a little reading on F# and decided to give it a try. I started with a somewhat involved example and I came up with and got lost immediately. I wonder if someone can share some thoughts on it.
I wanted to write a method called ComparisonStrategy<'T> that returns an instance of IEqualityComparer<'T>. It that takes in a variable length of ComparisonWhichAndHow<'T> instances. The type ComparisonWhichAndHow<'T> can either be:
One function of type ('T -> *), which is a method that selects a single field to compare
a 2-tuple of ('T -> 'U, IEqualityComparer<'U>) if you don't want the default Equals or GetHashCode to be used on 'U.
I have tried to draw this down on visual studio for a while now, but I can't even get the function declaration part right. I am somewhat positive I would be able to implement the method body if I can just get past this, but seems like I can't.
Edited:
This is the code I have tried so far.
I am trying to achieve the 2 following things.
Come up with a generic way of generating a equal method for each object.
Sometimes some business operations might require comparing some fields of 2 objects, and some fields of their children. Not a full comparison. I am trying to make writing those code more concise and simple
This is what I have so far:
module Failed =
open System.Collections.Generic
open System
type ComparsionOption<'T, 'U> =
| Compare of ('T -> 'U)
| CompareWith of ('T -> 'U) * IEqualityComparer<'U>
// TO USE: [<ParamArray>]
// TODO: this method returns a dummy for now
let CompareStrategy (opts : ComparsionOption<'T, _> array) =
EqualityComparer<'T>.Default
// How it's used
type Person(name : string, id : Guid) =
member this.Name = name
member this.ID = id
let fullCompare : EqualityComparer<Person> =
CompareStrategy [|Compare(fun (p : Person) -> p.Name);
CompareWith((fun (p : Person) -> p.ID), EqualityComparer<Guid>.Default)|] // error here
Looking at the problem from another perspective, it looks like you want to be able to construct objects that perform comparison in two different ways (which you specified) and then compose them.
Let's start by looking at the two ways to build an object that performs comparison. You can represent both by IEqualityComparer<'T>. The first one takes a function 'T -> Something and performs comparison on the result. You can define a function like this:
/// Creates a comparer for 'T values based on a predicate that
/// selects some value 'U from any 'T value (e.g. a field)
let standardComparer (f:'T -> 'U) =
{ new IEqualityComparer<'T> with
member x.Equals(a, b) =
(f a).Equals(b) // Call 'f' on the value & test equality of results
member x.GetHashCode(a) =
(f a).GetHashCode() } // Call 'f' and get hash code of the result
The function is 'T -> 'U using F# generics, so you can project fields of any type (the type just has to be comparable). The second primitive function also takes 'T -> 'U, but it also takes a comparer for 'U values instead of using the default:
/// Creates a comparer for 'T values based on a predicate & comparer
let equalityComparer (f:'T -> 'U) (comparer:IEqualityComparer<'U>) =
{ new IEqualityComparer<'T> with
member x.Equals(a, b) =
comparer.Equals(f a, f b) // Project values using 'f' and use 'comparer'
member x.GetHashCode(a) =
comparer.GetHashCode(f a) } // Similar - use 'f' and 'comparer'
Now you're saying that you'd like to take a sequence of values created in one of the two above ways to build a single comparison strategy. I'm not entirely sure what you mean by that. Do you want two objects to be equal when all the specified comparers report them as equal?
Assuming that is the case, you can write a function that combines two IEqualityComparer<'T> values and reports them as equal when both comparers report them as equal like this:
/// Creates a new IEqualityComparer that is based on two other comparers
/// Two objects are equal if they are equal using both comparers.
let combineComparers (comp1:IEqualityComparer<'T>) (comp2:IEqualityComparer<'T>) =
{ new IEqualityComparer<'T> with
member x.Equals(a, b) =
comp1.Equals(a, b) && comp2.Equals(a, b) // Combine results using &&
member x.GetHashCode(a) =
// Get hash code of a tuple composed by two hash codes
hash (comp1.GetHashCode(a), comp2.GetHashCode(a)) }
This is essenitally implementing all the functionality that you need. If you have some object Person, you can construct comparer like this:
// Create a list of primitive comparers that compare
// Name, Age and ID using special 'idComparer'
let comparers =
[ standardComparer (fun (p:Person) -> p.Name);
standardComparer (fun (p:Person) -> p.Age);
equalityComparer (fun (p:Person) -> p.ID) idComparer ]
// Create a single comparer that combines all of them...
let comparePerson = comparers |> Seq.reduce combineComparers
You could wrap this in a more object-oriented interface using overloaded methods etc., but I think that the above sample shows all the important components that you'll need in the solution.
BTW: In the example, I was using F# object expressions to implement all the functions.
I am trying to write a typed abstract syntax tree datatype that can represent
function application.
So far I have
type Expr<'a> =
| Constant of 'a
| Application of Expr<'b -> 'a> * Expr<'b> // error: The type parameter 'b' is not defined
I don't think there is a way in F# to write something like 'for all b' on that last line - am I approaching this problem wrongly?
In general, the F# type system is not expressive enough to (directly) define a typed abstract syntax tree as the one in your example. This can be done using generalized algebraic data types (GADTs) which are not supported in F# (although they are available in Haskell and OCaml). It would be nice to have this in F#, but I think it makes the language a bit more complex.
Technically speaking, the compiler is complaining because the type variable 'b is not defined. But of course, if you define it, then you get type Expr<'a, 'b> which has a different meaning.
If you wanted to express this in F#, you'd have to use a workaround based on interfaces (an interface can have generic method, which give you a way to express constraint like exists 'b which you need here). This will probably get very ugly very soon, so I do not think it is a good approach, but it would look something like this:
// Represents an application that returns 'a but consists
// of an argument 'b and a function 'b -> 'a
type IApplication<'a> =
abstract Appl<'b> : Expr<'b -> 'a> * Expr<'b> -> unit
and Expr<'a> =
// Constant just stores a value...
| Constant of 'a
// An application is something that we can call with an
// implementation (handler). The function then calls the
// 'Appl' method of the handler we provide. As this method
// is generic, it will be called with an appropriate type
// argument 'b that represents the type of the argument.
| Application of (IApplication<'a> -> unit)
To represent an expression tree of (fun (n:int) -> string n) 42, you could write something like:
let expr =
Application(fun appl ->
appl.Appl(Constant(fun (n:int) -> string n),
Constant(42)))
A function to evaluate the expression can be written like this:
let rec eval<'T> : Expr<'T> -> 'T = function
| Constant(v) -> v // Just return the constant
| Application(f) ->
// We use a bit of dirty mutable state (to keep types simpler for now)
let res = ref None
// Call the function with a 'handler' that evaluates function application
f { new IApplication<'T> with
member x.Appl<'A>(efunc : Expr<'A -> 'T>, earg : Expr<'A>) =
// Here we get function 'efunc' and argument 'earg'
// The type 'A is the type of the argument (which can be
// anything, depending on the created AST)
let f = eval<'A -> 'T> efunc
let a = eval<'A> earg
res := Some <| (f a) }
res.Value.Value
As I said, this is a bit really extreme workaround, so I do not think it is a good idea to actually use it. I suppose the F# way of doing this would be to use untyped Expr type. Can you write a bit more about the overall goal of your project (perhaps there is another good approach)?
I am trying to write a typed abstract syntax tree datatype that can represent
function application.
So far I have
type Expr<'a> =
| Constant of 'a
| Application of Expr<'b -> 'a> * Expr<'b> // error: The type parameter 'b' is not defined
I don't think there is a way in F# to write something like 'for all b' on that last line - am I approaching this problem wrongly?
In general, the F# type system is not expressive enough to (directly) define a typed abstract syntax tree as the one in your example. This can be done using generalized algebraic data types (GADTs) which are not supported in F# (although they are available in Haskell and OCaml). It would be nice to have this in F#, but I think it makes the language a bit more complex.
Technically speaking, the compiler is complaining because the type variable 'b is not defined. But of course, if you define it, then you get type Expr<'a, 'b> which has a different meaning.
If you wanted to express this in F#, you'd have to use a workaround based on interfaces (an interface can have generic method, which give you a way to express constraint like exists 'b which you need here). This will probably get very ugly very soon, so I do not think it is a good approach, but it would look something like this:
// Represents an application that returns 'a but consists
// of an argument 'b and a function 'b -> 'a
type IApplication<'a> =
abstract Appl<'b> : Expr<'b -> 'a> * Expr<'b> -> unit
and Expr<'a> =
// Constant just stores a value...
| Constant of 'a
// An application is something that we can call with an
// implementation (handler). The function then calls the
// 'Appl' method of the handler we provide. As this method
// is generic, it will be called with an appropriate type
// argument 'b that represents the type of the argument.
| Application of (IApplication<'a> -> unit)
To represent an expression tree of (fun (n:int) -> string n) 42, you could write something like:
let expr =
Application(fun appl ->
appl.Appl(Constant(fun (n:int) -> string n),
Constant(42)))
A function to evaluate the expression can be written like this:
let rec eval<'T> : Expr<'T> -> 'T = function
| Constant(v) -> v // Just return the constant
| Application(f) ->
// We use a bit of dirty mutable state (to keep types simpler for now)
let res = ref None
// Call the function with a 'handler' that evaluates function application
f { new IApplication<'T> with
member x.Appl<'A>(efunc : Expr<'A -> 'T>, earg : Expr<'A>) =
// Here we get function 'efunc' and argument 'earg'
// The type 'A is the type of the argument (which can be
// anything, depending on the created AST)
let f = eval<'A -> 'T> efunc
let a = eval<'A> earg
res := Some <| (f a) }
res.Value.Value
As I said, this is a bit really extreme workaround, so I do not think it is a good idea to actually use it. I suppose the F# way of doing this would be to use untyped Expr type. Can you write a bit more about the overall goal of your project (perhaps there is another good approach)?
let f (O: obj) =
match O with
| :? (obj -> list<obj>) -> "win"
| :? list<obj> -> "list!"
| _ -> "fail"
Console.WriteLine(f(fun x -> ["lol"]))
Console.WriteLine(f(["lol"]))
prints "fail" twice, as I suppose it should, because I am giving i a function obj -> list<String>, which is not a obj -> list<obj>. Is there any way to make them match though? I could upcast each list into a list<obj> before making an anonymous function out of it, or I could upcast everything to obj before putting it into the list.
Either of those works and makes it match, but i thought this was the problem that covariance/contravariance was meant to have already solved? Correct me if i'm mistaken
Unfortunately, you can't solve this using any built-in pattern matching.
The only way to find out whether an obj value is some F# function is to use F# Reflection and call the FSharpType.IsFunction method on the type. You can check for the case in your example like this:
open System
open Microsoft.FSharp.Reflection
let f (o : obj) =
let ty = o.GetType()
if FSharpType.IsFunction(ty) then
let tyFrom, tyTo = FSharpType.GetFunctionElements(ty)
if tyTo.IsGenericType && tyTo.GetGenericTypeDefinition() = typedefof<list<_>> then
printfn "win"
else
printfn "wrong function"
else
printfn "not a function"
Console.WriteLine(f(fun x -> "lol")) // wrong function
Console.WriteLine(f(fun x -> ["lol"])) // win
Console.WriteLine(f(["lol"])) // not a function
You could encapsulate the behavior in an F# active pattern to make the syntax a bit nicer (and use pattern matching on types). However, another problem is that this doesn't give you a function that you could use to actually invoke the function dynamically. I don't think there is a built-in library function for this, so you'll probably need to use .NET reflection to call the Invoke method dynamically.
EDIT: There has been similar related questions on SO. The general problem is that you're matching against some (any) instantiation of a specific generic type, so the same issue arises with lists etc. See for example:
F# and pattern matching on generics...
Pattern matching against generic type...
How to cast an object to a list...
Problem Summary
At the moment when using f# I must explicitly coerce a value to the parent type of its type in order to get pattern matching expressions to type check correctly. I would ideally like a neater way of doing.
Example
Suppose I have some class hierachy:
type Foo () =
abstract member Value : unit -> string
type A (i:int) =
inherit Foo ()
override this.Value () = i.ToString()
type B (s:string) =
inherit Foo ()
override this.Value () = s
Ideally, and in some programming languages in normally, I would write the equivalent of the following:
let bar (i:int) : Foo =
match i with
| 1 -> B "one"
| _ -> A i
However this fails to type check correctly, giving me the error, "This expression was expected to have type Foo but here has type B". I don't understand why the compiler doesn't have enough information to infer a common super type for the match expression and then check that the common super type is 'Foo'.
At present I am forced to provide an explicit coercion for every case in the pattern match:
let bar2 (i:int) : Foo =
match i with
| 1 -> (B "one") :> Foo
| _ -> (A i) :> Foo
I would like to avoid this.
Further Notes
Intuition suggests that this is a result of a more general issue. I would have thought though that something as common as pattern matching, or if statements which also exhibit the same property, would have a type checking rule to account for common super types.
Before anyone suggests - I appreciate that if A or B were Object Expressions this would work, but my real example is creating instances of C# classes where they are normal classes.
Is there a way for me to declare functions to implicitly convert types, as for example scala has, so I could apply automatic conversions for the module where I'm doing this generation?
Thanks for any help on this matter.
I would use upcast, a la
[<AbstractClass>]
type Foo () =
abstract member Value : unit -> string
type A (i:int) =
inherit Foo ()
override this.Value () = i.ToString()
type B (s) =
inherit Foo ()
override this.Value () = s
let bar2 i : Foo =
match i with
| 1 -> upcast B "one"
| _ -> upcast A i
You still have to add it to every branch, but this is often preferable to casting to the type, since often the typename is like 20 or 30 characters long (MyNamespace.ThisThingy), whereas upcast is just 6 characters.
But, briefly, the language rules don't allow for anything else, the types of all the branches have to be equal.
I've seen this question a couple of times before, but I just realized that there is quite an interesting way to workaround the issue (without any significant negative effects such as big runtime overhead).
You can use a very simple computation expression that has only Return member. The builder will have a type parameter and Return will expect values of this type. The trick is, that F# does insert automatic upcasts when calling a member. Here is the declaration:
type ExprBuilder<'T>() =
member x.Return(v:'T) = v
let expr<'T> = ExprBuilder<'T>()
To write a simple pattern matching that returns anything as obj, you can now write:
let foo a = expr<obj> {
match a with
| 0 -> return System.Random()
| _ -> return "Hello" }
You still have to be explicit about the return type (when creating the computation expression), but I find the syntax quite neat (but it is definitely a tricky use that could confuse people who'll see it for the first time).