Is it possible to somehow use a pipeline to pass in the last argument of a method with tupled parameters?
An example:
// Member to call
static member Property (expr:Expr<'a -> string>, cfg:EntityInfo<'a>) = cfg.Property expr
// My curry function
let curry f x y = f (x,y)
// My EntityInfo<FileUpload>
let entityInfo = EF.Entity<FileUpload> modelBuilder
I want to be able to call it like:
entityInfo |> curry EF.Property <# fun z -> z.Path #>
instead of
EF.Property(<# fun z -> z.Path #>, entityInfo)
I believe that this is a simplified version of your problem (although you're excluding too much code to be sure):
type T() = class end
type S =
static member Method(_:int, T) = 'c'
static member Method(_:string, T) = false
let curry f x y = f(x,y)
// won't work
T() |> curry S.Method 1
As Brian mentions, overloading doesn't play nicely with type inference. In particular, since F#'s type inference works left-to-right, the compiler does not use the fact that 1 is an int when trying to do the member lookup for S.Method, which means that it can't identify the correct overload. As I see it, you have a few options:
Use distinct method names. Is there a reason that you have to use Property to refer to multiple different operations? Would it be much worse to use StringProperty, IntProperty, etc. for each overload? In general, overloading makes life harder for the compiler (and often for human maintainers, too). As an aside, I don't like the idea of naming a method Property, anyway...
Use explicit type parameters on curry, and specify them. E.g.
let curry<'a,'b,'c> f (x:'a) (y:'b) : 'c = f(x,y)
entityInfo |> curry<Expr<_ -> string>,_,_> EF.Property <# fun z -> z.Path #>
Explicitly indicate the type of EF.Property:
entityInfo |> curry (EF.Property: Expr<_ -> string> * _ -> _) <# fun z -> z.Path #>
Of course, these last two options aren't very concise, so they may defeat the purpose of using the pipelined style.
It is because it is counting entity info as an member of EF.Propery method instead of curry method, you should use
entityInfo |> curry (EF.Property) (<# fun z -> z.Path #>)
Related
F# does not (currently) support type-classes. However, F# does support the OOP aspects of C#.
I was wondering, what is lost doing this approach compared to true type-classes?
// A concrete type
type Foo =
{
Foo : int
}
// "Trait" for things that can be shown
type IShowable =
abstract member Show : unit -> string
module Showable =
let show (showable : IShowable) =
showable.Show()
// "Witness" of IShowable for Foo
module Foo =
let asShowable (foo : Foo) =
{
new IShowable with
member this.Show() = string foo.Foo
}
// Slightly awkward usage
{ Foo = 123 }
|> Foo.asShowable
|> Showable.show
|> printfn "%s"
Your suggestion works for simple typeclasses that operate on a single value of a type, like Show. However, what happens when you need a typeclass that isn't so object-oriented? For example, when we want to add two numbers, neither one corresponds to OO's this object:
// not real F#
typeclass Numeric<'a> = // e.g. Numeric<int> or Numeric<float>
abstract member (+) : 'a -> 'a -> 'a // e.g. 2 + 3 = 5 or 2.0 + 3.0 = 5.0
...
Also, keep in mind that many useful typeclasses require higher-kinded types. For example, consider the monad typeclass, which would look something like this:
// not real F#
typeclass Monad<'m<_>> = // e.g. Monad<Option<_>> or Monad<Async<_>>
abstract member Return<'a> : 'a -> 'm<'a>
abstract member Bind<'a, 'b> : 'm<'a> -> ('a -> 'm<'b>) -> 'm<'b>
There's no good way to do this with .NET interfaces.
Higher-kinded type classes are indeed impossible to model with interfaces, but that's just because F# does not support higher-kindedness, not because of type classes themselves.
The deeper thing to note is that your encoding isn't actually correct. Sure, if you just need to call show directly, you can do asShowable like that, but that's just the simplest case. Imagine you needed to pass the value to another function that wanted to show it later? And then imagine it was a list of values, not a single one:
let needsToShow (showable: IShowable) (xs: 'a list) =
xs |> List.iter (fun x -> ??? how do I show `x` ???)
No, this wouldn't do of course. The key is that Show should be a function 'a -> string, not unit -> string. And this means that IShowable itself should be generic:
// Haskell: class Showable a where show :: a -> String
type IShowable<'a> with
abstract member Show : 'a -> string
// Haskell: instance Showable Foo where show (Foo i) = show i
module Foo =
let showable = { new IShowable<Foo> with member _.Show foo = string foo.Foo }
// Haskell: needsToShow :: Show a => [a] -> IO ()
let needsToShow (showable: IShowable<'a>) (xs: 'a list) =
xs |> List.iter (fun x -> printfn "%s" (showable.Show x))
// Haskell: needsToShow [Foo 1, Foo 42]
needsToShow Foo.showable [ { Foo: 1 }; { Foo: 42 } ]
And this is, essentially, what type classes are: they're indeed merely dictionaries of functions that are passed everywhere as extra parameters. Every type has such dictionary either available right away (like Foo above) or constructable from other such dictionaries, e.g.:
type Bar<'a> = Bar of 'a
// Haskell: instance Show a => Show (Bar a) where show (Bar a) = "Bar: " <> show a
module Bar =
let showable (showA: IShowable<'a>) =
{ new IShowable<Bar<'a>> with member _.Show (Bar a) = "Bar: " + showA.Show a }
This is completely equivalent to type classes. And in fact, this is exactly how they're implemented in languages like Haskell or PureScript in the first place: like dictionaries of functions being passed as extra parameters. It's not a coincidence that constraints on function type signatures even kinda look like parameters - just with a fat arrow instead of a thin one.
The only real difference is that in F# you have to do that yourself, while in Haskell the compiler figures out all the instances and passes them for you.
And this difference turns out to be kind of important in practice. I mean, sure, for such a simple example as Show for the immediate parameter, you can just pass the damn instance yourself. And even if it's more complicated, I guess you could suck it up and pass a dozen extra parameters.
But where this gets really inconvenient is operators. Operators are functions too, but with operators there is nowhere to stick an extra parameter (or dozen). Check this out:
x = getY >>= \y -> getZ y <&> \z -> y + 42 > z
Here I used four operators from four different classes:
>>= comes from Monad
<&> from Functor
+ from Num
> from Ord
An equivalent in F# with passing instances manually might look something like:
let x =
bind Foo.monad getY <| fun y ->
map Bar.functor (getZ y) <| fun z ->
gt Int.ord (add Int.num y 42) z
Having to do that everywhere is quite unreasonable, you have to agree.
And this is why many F# operators either use SRTPs (e.g. +) or rely on "known" interfaces (e.g. <) - all so you don't have to pass instances manually.
This code snippet reproduces a problem I am having with some production code. The function containsProperty represents a real world function that is actually in a library, so that I have no say in what the signature is.
The problem is that I can't figure out how to create a wrapper function that can take a normal function as argument, and then pass that on to containsProperty. I can call containsProperty directly with a function as a lambda expression, but I can't call it with a function that comes from some other source.
The function addToGroup is the best I've come up with so far, and it uses quotations. There are two problems with that approach, which I am trying to figure out. First, how do I get rid of the Func cast in the quotation? Perhaps somehow move it into addToGroup? Second, can I build on this in order to just pass a function? I haven't succeeded in finding something that doesn't produce either a compile time error or a runtime error.
The function addToGroup2 is what I'd like to do, but it doesn't compile. The error message is "No constructors are available for the type 'Quotations.Expr<'a>'".
Why do I bother to struggle with this? Because as long as I can't treat the passed in function as a first class value, I can't create the design I'm after. I want these functions to come along from a collection of records.
If you paste this snippet into LINQPad or something, comment out addToGroup2 and the calls to it, in order to make the snippet compile and run.
open System
open System.ComponentModel
open System.ComponentModel.DataAnnotations // Reference to this assembly required.
type CfgSettings = {
mutable ConnectionString: string
mutable Port: int
}
and CfgSettingsMetadata() =
static member containsProperty<'TProperty>(propertyExpression: Linq.Expressions.Expression<Func<CfgSettings,'TProperty>>) =
Console.WriteLine "good!"
static member addToGroup f =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
static member addToGroup2 (f: CfgSettings -> 'TProperty) =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression (Quotations.Expr<Func<CfgSettings,'TProperty>>f)) |> ignore
static member BuildMetadata () =
CfgSettingsMetadata.containsProperty(fun x -> x.ConnectionString)
CfgSettingsMetadata.containsProperty(fun x -> x.Port)
CfgSettingsMetadata.addToGroup <# Func<_,_>(fun x -> x.ConnectionString) #>
CfgSettingsMetadata.addToGroup <# Func<_,_>(fun x -> x.Port) #>
CfgSettingsMetadata.addToGroup2 (fun x -> x.ConnectionString)
CfgSettingsMetadata.addToGroup2 (fun x -> x.Port)
CfgSettingsMetadata.BuildMetadata()
Both answers in question Expression<Func<T, bool>> from a F# func helped me somewhat, but I haven't found a solution yet.
So, there are two questions here.
How to pass a function without having to wrap it in <# ... #>?
For this, you just need to add the [<ReflectedDefinition>] attribute to your method's parameter. It implicitly wraps the argument passed to it in a quotation.
type CfgSettingsMetadata() =
static member addToGroup([<ReflectedDefinition>] f: Expr<CfgSettings -> 'TProperty>) =
CfgSettingsMetadata.containsProperty(LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
// Example use:
CfgSettingsMetadata.addToGroup(Func<_, _>(fun x -> x.ConnectionString))
How to convert from Expr<a -> b> to Expression<Func<a, b>>?
This is indeed explained in the question you linked, although the API has changed a bit since then.
type CfgSettingsMetadata() =
static member addToGroup ([<ReflectedDefinition>] (f: Expr<CfgSettings -> 'TProperty>)) =
let call = LeafExpressionConverter.QuotationToExpression f :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
let e = Expression.Lambda<Func<CfgSettings, 'TProperty>>(lambda.Body, lambda.Parameters)
CfgSettingsMetadata.containsProperty(e) |> ignore
// Example use:
CfgSettingsMetadata.addToGroup(fun x -> x.ConnectionString)
I have two example types, defined in this order:
type Quote = {QuoteNum: decimal option; ShipToID: decimal option}
type Sales = {SalesNum: decimal option; ShipToID: decimal option}
and I'm trying to write a function that can accept a both types:
let fx (y: Map<decimal option, _ list>) =
y
|> Map.map (fun key list -> list
|> List.map (fun x -> x.ShipToID))
When I try to pass a Map<decimal option, Quote list> to the function, I get an error:
Type mismatch. Expecting a
Map<decimal option,Sales list>
but given a
Map<decimal option,Quote list>
I would have thought that I'd be able to pass a map of both types to the function, but the compiler seems to be inferring that only a Map<decimal option, Sales list> is acceptable to the function. I suspect that the compiler "sees" the Sales type most recently and assumes that that's what the function needs. I thought I had made the function relatively generic by including the _ in the type annotation.
How can I make the function accept both types? Can I do this without redefining the types themselves?
Your suspicions are correct. F# needs to infer a single concrete type there, so will use the most recent matching type it finds.
You can make it work by defining an interface with ShipToID field and have both types implement it (not sure if that counts as redefining the types for you), or by providing a getter function for extracting the field value (which would let you keep the function generic):
let fx (shipToIdGetter: 'a -> decimal option) (y: Map<decimal option, 'a list>) =
y
|> Map.map (fun key list ->
list
|> List.map (fun x -> shipToIdGetter x))
Your code would work as written if F# supported row polymorphism (which happens to be the case for OCaml).
While I believe that scrwtp's answer is the way to go, you also have the choice to use inline and member constraints (or static duck typing...if thats a valid term). For the sake of completeness:
type Quote = {QuoteNum: decimal option; ShipToID: decimal option}
type Sales = {SalesNum: decimal option; ShipToID: decimal option}
let inline fx (y: Map<decimal option, 'a list>) =
let inline getId x = ( ^a : (member ShipToID : decimal option) x)
y |> Map.map (fun key list -> list |> List.map getId)
let q : Quote = { QuoteNum = None; ShipToID = None}
let s : Sales = { SalesNum = None; ShipToID = None}
fx <| Map.ofList [ None, [q]]
fx <| Map.ofList [ None, [s]]
The getId function uses the rather obscure syntax to call the ShipToID member based on ^a's expected structure.
I have a Dictionary over which I initially iterated thusly:
myDictionary |> Seq.iter (fun kvp -> doSomething kvp.Key kvp.Value)
Later, I discovered that I could make use of the KeyValue active pattern, and do this:
myDictionary |> Seq.iter (fun (KeyValue (k, v)) -> doSomething k v)
Knowing that active patterns aren't some form of preprocessor directive, how am I able to substitute the kvp argument in the lambda for a function that decomposes it?
Functions arguments call always be destructured using pattern matching. For instance:
let getSingleton = fun [x] -> x
let getFirst = fun (a,b) -> a
let failIfNotOne = fun 1 -> ()
let failIfNeitherOne = fun (x,1 | 1,x) -> ()
Semantically, fun<pat>-><body> is roughly equivalent to
fun x -> match x with |<pat>-><body>
| _ -> raise MatchFailureException(...)
I think the answer from #kvb covers in enough details why you can use patterns in the arguments of fun. This is not an ad-hoc feature - in F#, you can use patterns anywhere where you can bind a variable. To show some of the examples by #kvb in another contexts:
// When declaring normal functions
let foo [it] = it // Return the value from a singleton list
let fst (a, b) = a // Return first element of a pair
// When assigning value to a pattern using let
let [it] = list
let (a, b) = pair
Similarly, you can use patterns when writing fun. The match construct is a bit more powerful, because you can specify multiple clauses.
Now, active patterns are not really that magical. They are just normal functions with special names. The compiler searches for active patterns in scope when it finds a named pattern. For example, the pattern you're using is just a function:
val (|KeyValue|) : KeyValuePair<'a,'b> -> 'a * 'b
The pattern turns a KevValuePair object into a normal F# tuple that is then matched by a nested pattern (k, v) (which assigns the first element to k and the second to v). The compiler essentially translates your code to:
myDictionary |> Seq.iter (fun _arg0 ->
let _arg1 = (|KeyValue|) _arg0
let (k, v) = _arg1
doSomething k v )
To create a sequence of my class,
type MyInt(i:int) =
member this.i = i
[1;2;3] |> Seq.map(fun x->MyInt(x))
where fun x->MyInt(x) seems to be redundant. It would be better if I can write Seq.map(MyInt)
But I cannot. One workaround I can think of is to define a separate function
let myint x = MyInt(x)
[1;2;3] |> Seq.map(myint)
Is there a better way to do this?
If gratuitous hacks don't bother you, you could do:
///functionize constructor taking one arg
let inline New< ^T, ^U when ^T : (static member ``.ctor`` : ^U -> ^T)> arg =
(^T : (static member ``.ctor`` : ^U -> ^T) arg)
type MyInt(i: int) =
member x.i = i
[0..9] |> List.map New<MyInt, _>
EDIT: As kvb pointed out, a simpler (and less hacky) signature can be used:
let inline New x = (^t : (new : ^u -> ^t) x)
Note, this switches the type args around, so it becomes New<_, MyInt>.
In short, no.
Object constructors aren't first-class functions in F#. This is one more reason to not use classes, discriminated unions is better to use here:
type myInt = MyInt of int
let xs = [1;2;3] |> Seq.map MyInt
If you don't like explicit lambdas, sequence expression looks nicer in your example:
let xs = seq { for x in [1;2;3] -> MyInt x }
Alternatively, your workaround is a nice solution.
To give an update on this - F# 4.0 has upgraded constructors to first-class functions, so they can now be used anywhere a function or method can be used.
I use static methods for this purpose. The reason is that sometimes your object constructor needs two arguments taken from different sources, and my approach allows you to use List.map2:
type NumRange(value, range) =
static member Make aValue aRange = new NumRange(aValue, aRange)
let result1 = List.map2 NumRange.Make values ranges
Partial application is not prohibited as well:
let result2 =
values
|> List.map NumRange.Make
|> List.map2 id <| ranges
If you dislike using id here, you may use (fun x y -> x y) which is more readable.