I'm trying to do this:
data A = a(str s);
void show(A a(str s)) = println(s);
A x = a("hi");
show(x);
but I get this error:
|prompt:///|(0,7,<1,0>,<1,7>): The called signature: show(A),
does not match the declared signature: void show(node);
Is this because this is currently broken (as the tutor page for TypeConstrained abstract patterns suggests), or am I making a mistake?
I think it should be
void show(a(str s)) = println(s);
where did you see this A prefix in the tutor?
Related
I've read the-f-equivalent-of-cs-out but still I can't make it work for my case (the simplest solution/syntax).
I have this method in a C# project:
//<Project Sdk="Microsoft.NET.Sdk">
//<TargetFrameworks>netcoreapp3.1;netstandard2.0</TargetFrameworks>
public static void ABC(out byte[] a, out byte[] b, byte[] c)
{
var aaa = new byte[10];
var bbb = new byte[10];
a = aaa;
b = bbb;
}
Now, I want to use it in a F# project:
I'm using FSharp.Core 4.7.2
(* <Project Sdk="Microsoft.NET.Sdk">
<TargetFrameworks>netcoreapp3.1;netstandard2.0</TargetFrameworks> *)
let a,b = ABC(c)
I'm imitating the syntax of TryParse and this compiles without errors:
let success, number = System.Int32.TryParse("0")
The compiler on my ABC(c) call complains about the fact the signature asks for 3 parameters, not 1.
Compared to the TryParse I see 2 differences:
It does not return void
It uses Array objects
The compiler accepts this syntax:
let a = Array.empty<byte>
let b = Array.empty<byte>
ABC(ref a, ref b, c)
but:
I think it is not correct to use ref here, not in this way (because a and b are not mutable)
I'd like to use the clean syntax similar to TryParse and I WANT to know why it does not work here
I can change the C# project code, but replacing all the out parameters in that proejct will be a second step and maybe a new qeustion if I have difficulties or doubt.
[Update: parameter position]
I played a little with this and seems like I found when the "simple" syntax (without passing ref parameters) is broken.
public static void TryParseArray(string input, out int[] result) {
result = new int[0];
}
public static void TryParseArray_2(out int[] result, string input) {
result = new int[0];
}
let arr = csharp.TryParseArray("a") // OK
let arr = csharp.TryParseArray_2("a") // ERROR
It seems like the out parameter must be at the end (= not followed by normal parameters) in the C# methods, to make possible for F# to use them as returned tuple.
You correctly noticed that the "simplified" F# syntax for turning out parameters into returned tuples only works in very limited situations - only when you have one parameter and it is the last one. In other words, this feature helps with some common patterns, but it does not fully replace out parameters.
If you want to use out parameter in F#, you can either pass a reference to a local mutable variable using the &var syntax, or you can specify a reference cell of type int ref as an argument. The following shows the two options using the standard TryParse method:
// Using a local mutable variable
let mutable n = 0
Int32.TryParse("42", &n)
printfn "Got: %d" n
// Using a reference cell initialized to 0
let n = ref 0
Int32.TryParse("42", n)
printfn "Got: %d" n.Value
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)
In my previous question Kurt pointed me to this code of FsCheck about setting the Arbitrary type.
I have the following Arbitrary (disclaimer: I have no idea what I am doing..., still finding FsCheck notoriously hard to understand but I'm dead set on getting it to work), which in itself is a simplified version of something I created earlier:
type MyArb() =
inherit Arbitrary<DoNotSize<int64>>()
override x.Generator = Arb.Default.DoNotSizeInt64().Generator
And I use it as instructed:
[<Property(Verbose = true, Arbitrary= [| typeof<MyArb> |])>]
static member MultiplyIdentity (x: int64) = x * 1L = x
This gives me a (somewhat hopeful) error message that I'm missing something:
System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
----> System.Exception : No instances found on type Tests.Arithmetic.MyArb. Check that the type is public and has public static members with the right signature.
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at FsCheck.Runner.checkMethod(Config config, MethodInfo m, FSharpOption`1 target) in C:\Users\Kurt\Projects\FsCheck\FsCheck\src\FsCheck\Runner.fs:line 318
at FsCheck.NUnit.Addin.FsCheckTestMethod.runTestMethod(TestResult testResult) in C:\Users\Kurt\Projects\FsCheck\FsCheck\src\FsCheck.NUnit.Addin\FsCheckTestMethod.fs:line 100
Looking back at that Github code I see two Atrbitrary classes but neither with any inheritance and they both have different static members.
How can I create a random-number generator and assign it as an Arbitrary statically to my NUnit tests?
The type you provide in the Property.Arbitrary parameter should have static members (possibly several) of type Arb. As in the code you linked:
type TestArbitrary2 =
static member NegativeDouble() =
Arb.Default.Float()
|> Arb.mapFilter (abs >> ((-) 0.0)) (fun t -> t <= 0.0)
Applying this to your code, it should look like this:
type MyArb() =
static member m() = Arb.Default.DoNotSizeInt64()
The meaning of the Property.Arbitrary parameter is not "an implementation of Arbitrary", but rather "a bucket of typeclass implementations".
You see, the original Haskell implementation of QuickCheck relies on typeclasses to provide values of different types. In order for a particular type to be "quick-checkable", there needs to be an instance of the 'Arbitrary' class defined for that type (for example, here are instances for all basic types).
Since F# doesn't support type classes as such, FsCheck has to fake it, and this is the scheme used there: each type class instance is represented by a static member that returns the function table. For example, if we wanted to simulate the Eq typeclass, we'd define it something like this:
type Eq<'a> = { eq: 'a -> 'a -> bool; neq: 'a -> 'a -> bool }
type EqInstances() =
static member ForInt() : Eq<int> =
{ eq = (=); neq = (<>) }
static member ForMyCustomType() : Eq<MyCustomType> =
{ eq = fun a b -> a.CompareTo(b) = 0
neq = fun a b -> a.CompareTo(b) <> 0 }
But because you can't just scan all static member in all loaded assemblies (that would be prohibitively expensive), there is this little inconvenience of providing the type explicitly (as a bonus, it allows to control the visibility of "instances").
This question demonstrates clearly, IMO, why the Reflection-based API for FsCheck is less than ideal. I tend to avoid that API completely, so I'd instead write the OP property like this:
open FsCheck
open FsCheck.Xunit
[<Property>]
let MultiplyIdentity () =
Arb.Default.DoNotSizeInt64 () |> Prop.forAll <| fun (DoNotSize x) -> x * 1L = x
As the open directives suggest, this uses FsCheck.Xunit instead of FsCheck.NUnit, but AFAIK, there's no difference in the way the API works.
The advantage of this approach is that it's type-safe and more lightweight, because you don't have to implement static classes every time you need to tweak FsCheck.
If you prefer the approach described by Mark Seemann, then you may also consider using plain-FsCheck and get rid of FsCheck.Xunit entirely:
module Tests
open FsCheck
let [<Xunit.Fact>] ``Multiply Identity (passing)`` () =
Arb.Default.DoNotSizeInt64 ()
|> Prop.forAll
<| fun (DoNotSize x) ->
x * 1L = x
|> Check.QuickThrowOnFailure
let [<Xunit.Fact>] ``Multiply Identity (failing)`` () =
Arb.Default.DoNotSizeInt64 ()
|> Prop.forAll
<| fun (DoNotSize x) ->
x * 1L = -1L |# sprintf "(%A should equal %A)" (x * 1L) x
|> Check.QuickThrowOnFailure
xUnit.net testrunner output:
------ Test started: Assembly: Library1.dll ------
Test 'Tests.Multiply Identity (failing)' failed: System.Exception:
Falsifiable, after 1 test (2 shrinks) (StdGen (2100552947,296238694)):
Label of failing property: (0L should equal 0L)
Original:
DoNotSize -23143L
Shrunk:
DoNotSize 0L
at <StartupCode$FsCheck>.$Runner.get_throwingRunner#365-1.Invoke(String me..
at <StartupCode$FsCheck>.$Runner.get_throwingRunner#355.FsCheck-IRunner-On..
at FsCheck.Runner.check[a](Config config, a p)
at FsCheck.Check.QuickThrowOnFailure[Testable](Testable property)
C:\Users\Nikos\Desktop\Library1\Library1\Library1.fs(15,0): at Tests.Multi..
1 passed, 1 failed, 0 skipped, took 0.82 seconds (xUnit.net 2.1.0 build 3179).
When I extend a type with a new function, I usually want it to be available from both dot-notation and free form. Either can be more readable depending on the situation, and the former helps with IntelliSense while the latter helps with currying.
In C#/VB.net, extension methods do this (although I cannot restrict the function to a static method of the extended static class, as in F#). I can write the function once and then invoke it both ways:
<Extension>
public function bounded(s as string, min as UShort, max as UShort) as string
if min > max then throw new ArgumentOutOfRangeException
if string.IsNullOrEmpty(s) then return new string(" ", min)
if s.Length < min then return s.PadRight(min, " ")
if s.Length > max then return s.Substring(0, max)
return s
end function
' usage
dim b1 = bounded("foo", 10, 15)
dim b2 = "foo".bounded(0, 2)
(That's not quite perfect yet, as I'd like bounded to be a static method of String, but C#/VB.Net can't do that. Point to F# in that regard.)
In F#, on the other side, I have to declare the function separatedly from the method:
// works fine
[<AutoOpen>]
module Utilities =
type List<'T> with
member this.tryHead = if this.IsEmpty then None else Some this.Head
module List =
let tryHead (l : List<'T>) = l.tryHead
Question: Is there a more elegant way to declare both methods at once?
I tried to use:
// doesn't quite work
type List<'T> with
member this.tryHead = if this.IsEmpty then None else Some this.Head
static member tryHead(l : List<'T>) = l.tryHead
which at least would let me skip the module declaration, but while the definition compiles, it doesn't quite work - someList.tryHead is OK, but List.tryHead someList results in a Property tryHead is not static error.
Bonus question: As you can see, the static member definition requires a type annotation. However, no other type could have access to the method that was just defined. Why, then, can't the type be inferred?
I don't know of a way to declare both APIs in a single line of code, but you can get rid of the type annotations by making the function the implementation, and then defining the method it terms of the function:
[<AutoOpen>]
module Utilities =
module List =
let tryHead l = if List.isEmpty l then None else Some (List.head l)
type List<'a> with
member this.tryHead = List.tryHead this
I know virtually nothing about F#. I don’t even know the syntax, so I can’t give examples.
It was mentioned in a comment thread that F# can declare functions that can take parameters of multiple possible types, for example a string or an integer. This would be similar to method overloads in C#:
public void Method(string str) { /* ... */ }
public void Method(int integer) { /* ... */ }
However, in CIL you cannot declare a delegate of this form. Each delegate must have a single, specific list of parameter types. Since functions in F# are first-class citizens, however, it would seem that you should be able to pass such a function around, and the only way to compile that into CIL is to use delegates.
So how does F# compile this into CIL?
This question is a little ambiguous, so I'll just ramble about what's true of F#.
In F#, methods can be overloaded, just like C#. Methods are always accessed by a qualified name of the form someObj.MethodName or someType.MethodName. There must be context which can statically resolve the overload at compile-time, just as in C#. Examples:
type T() =
member this.M(x:int) = ()
member this.M(x:string) = ()
let t = new T()
// these are all ok, just like C#
t.M(3)
t.M("foo")
let f : int -> unit = t.M
let g : string-> unit = t.M
// this fails, just like C#
let h = t.M // A unique overload for method 'M' could not be determined
// based on type information prior to this program point.
In F#, let-bound function values cannot be overloaded. So:
let foo(x:int) = ()
let foo(x:string) = () // Duplicate definition of value 'foo'
This means you can never have an "unqualified" identifier foo that has overloaded meaning. Each such name has a single unambiguous type.
Finally, the crazy case which is probably the one that prompts the question. F# can define inline functions which have "static member constraints" which can be bound to e.g. "all types T that have a member property named Bar" or whatnot. This kind of genericity cannot be encoded into CIL. Which is why the functions that leverage this feature must be inline, so that at each call site, the code specific-to-the-type-used-at-that-callsite is generated inline.
let inline crazy(x) = x.Qux(3) // elided: type syntax to constrain x to
// require a Qux member that can take an int
// suppose unrelated types U and V have such a Qux method
let u = new U()
crazy(u) // is expanded here into "u.Qux(3)" and then compiled
let v = new V()
crazy(v) // is expanded here into "v.Qux(3)" and then compiled
So this stuff is all handled by the compiler, and by the time we need to generate code, once again, we've statically resolved which specific type we're using at this callsite. The "type" of crazy is not a type that can be expressed in CIL, the F# type system just checks each callsite to ensure the necessary conditions are met and inlines the code into that callsite, a lot like how C++ templates work.
(The main purpose/justification for the crazy stuff is for overloaded math operators. Without the inline feature, the + operator, for instance, being a let-bound function type, could either "only work on ints" or "only work on floats" or whatnot. Some ML flavors (F# is a relative of OCaml) do exactly that, where e.g. the + operator only works on ints, and a separate operator, usually named +., works on floats. Whereas in F#, + is an inline function defined in the F# library that works on any type with a + operator member or any of the primitive numeric types. Inlining can also have some potential run-time performance benefits, which is also appealing for some math-y/computational domains.)
When you're writing C# and you need a function that can take multiple different parameter sets, you just create method overloads:
string f(int x)
{
return "int " + x;
}
string f(string x)
{
return "string " + x;
}
void callF()
{
Console.WriteLine(f(12));
Console.WriteLine(f("12"));
}
// there's no way to write a function like this:
void call(Func<int|string, string> func)
{
Console.WriteLine(func(12));
Console.WriteLine(func("12"));
}
The callF function is trivial, but my made-up syntax for the call function doesn't work.
When you're writing F# and you need a function that can take multiple different parameter sets, you create a discriminated union that can contain all the different parameter sets and you make a single function that takes that union:
type Either = Int of int
| String of string
let f = function Int x -> "int " + string x
| String x -> "string " + x
let callF =
printfn "%s" (f (Int 12))
printfn "%s" (f (String "12"))
let call func =
printfn "%s" (func (Int 12))
printfn "%s" (func (String "12"))
Being a single function, f can be used like any other value, so in F# we can write callF and call f, and both do the same thing.
So how does F# implement the Either type I created above? Essentially like this:
public abstract class Either
{
public class Int : Test.Either
{
internal readonly int item;
internal Int(int item);
public int Item { get; }
}
public class String : Test.Either
{
internal readonly string item;
internal String(string item);
public string Item { get; }
}
}
The signature of the call function is:
public static void call(FSharpFunc<Either, string> f);
And f looks something like this:
public static string f(Either _arg1)
{
if (_arg1 is Either.Int)
return "int " + ((Either.Int)_arg1).Item;
return "string " + ((Either.String)_arg1).Item;
}
Of course you could implement the same Either type in C# (duh!), but it's not idiomatic, which is why it wasn't the obvious answer to the previous question.
Assuming I understand the question, in F# you can define expressions which depend on the availability of members with particular signatures. For instance
let inline f x a = (^t : (member Method : ^a -> unit)(x,a))
This defines a function f which takes a value x of type ^t and a value a of type ^a where ^t has a method Method taking an ^a to unit (void in C#), and which calls that method. Because this function is defined as inline, the definition is inlined at the point of use, which is the only reason that it can be given such a type. Thus, although you can pass f as a first class function, you can only do so when the types ^t and ^a are statically known so that the method call can be statically resolved and inserted in place (and this is why the type parameters have the funny ^ sigil instead of the normal ' sigil).
Here's an example of passing f as a first-class function:
type T() =
member x.Method(i) = printfn "Method called with int: %i" i
List.iter (f (new T())) [1; 2; 3]
This runs the method Method against the three values in the list. Because f is inlined, this is basically equivalent to
List.iter ((fun (x:T) a -> x.Method(a)) (new T())) [1; 2; 3]
EDIT
Given the context that seems to have led to this question (C# - How can I “overload” a delegate?), I appear not to have addressed your real question at all. Instead, what Gabe appears to be talking about is the ease with which one can define and use discriminated unions. So the question posed on that other thread might be answered like this using F#:
type FunctionType =
| NoArgument of (unit -> unit)
| ArrayArgument of (obj[] -> unit)
let doNothing (arr:obj[]) = ()
let doSomething () = printfn "'doSomething' was called"
let mutable someFunction = ArrayArgument doNothing
someFunction <- NoArgument doSomething
//now call someFunction, regardless of what type of argument it's supposed to take
match someFunction with
| NoArgument f -> f()
| ArrayArgument f -> f [| |] // pass in empty array
At a low level, there's no CIL magic going on here; it's just that NoArgument and ArrayArgument are subclasses of FunctionType which are easy to construct and to deconstruct via pattern matching. The branches of the pattern matching expression are morally equivalent to a type test followed by property accesses, but the compiler makes sure that the cases have 100% coverage and don't overlap. You could encode the exact same operations in C# without any problem, but it would be much more verbose and the compiler wouldn't help you out with exhaustiveness checking, etc.
Also, there is nothing here which is particular to functions; F# discriminated unions make it easy to define types which have a fixed number of named alternatives, each one of which can have data of whatever type you'd like.
I'm not quite sure that understand your question correctly... F# compiler uses FSharpFunc type to represent functions. Usually in F# code you don't deal with this type directly, using fancy syntactic representation instead, but if you expose any members that returns or accepts function and use them from another language, line C# - you will see it.
So instead of using delegates - F# utilizes its special type with concrete or generic parameters.
If your question was about things like add something-i-don't-know-what-exactly-but-it-has-addition-operator then you need to use inline keyword and compiler will emit function body in the call site. #kvb's answer was describing exactly this case.