I have tried MSDN's example for the Seq.choose function (written below) in both a .fsx file and the interactive window for Visual Studio, but it repeatedly returns an error FS0001, stating that the "None" option is a PageExt type rather than the abstract option type 'a option.
I have searched in vain for an explanation of the PageExt type or why this could be returning an error when the None keyword should just represent the "no value" option in the match expression.
let numbers = seq {1..20}
let evens = Seq.choose(fun x ->
match x with
| x when x%2=0 -> Some(x)
| _ -> None ) numbers
printfn "numbers = %A\n" numbers
printfn "evens = %A" evens
;;
| _ -> None ) numbers
---------------------------------------^^^^
>
C:Path\stdin(38,40): error FS0001: This expression was expected to have type
'a option
but here has type
PageExt
Thanks for any help anyone can offer!
The PageExt type is likely something that you've pulled into your current FSI session previously which bound something to None, essentially blocking FSI from recognizing the normal option types.
In F#, you can reuse names, which "shadows" the original value. For example, in FSI, if you type:
let a = 1;;
let a = 2.3;;
a;;
You'll notice that it shows:
val a : int = 1
Then
val a : float = 2.3
Finally
val it : float = 2.3
This isn't changing the definition of a, but rather defining a new a name that shadows (or "hides") the original bound value.
In your case, you have a None name that's bound to something with a PageExt type that's shadowing Option.None, preventing it from being usable.
The easiest way to fix this is to reset your FSI session. Right click in the F# Interactive window, and choose "Reset iteractive session". If you do that, then run the code you pasted, it will work fine.
Related
I have a couple of wrappers of Printf-family API (e.g. for logging)
type Logger(writer: TextWriter) =
...
member x.Log (fmt: PrintfFormat<'Printer, _, _, _>): 'Printer =
Printf.fprintfn writer fmt
Let's say I want to introduce the notion of "log level" to it, add Logger.Info(), Debug(), Trace() etc. which are basically another layer on top of Logger.Log(), and if logger.Level <- LogLevel.Info then Debug() and Trace() should turn into no-ops. Pretty common requirement, I'd say.
But I can't seem to return a 'Printer-typed value without actually calling any of Printf-family API.
type LogLevel = TRACE | DEBUG | INFO
type LevelLogger(writer: TextWriter, level: LogLevel) =
inherit Logger(writer)
member x.Info (fmt: PrintfFormat<'Printer, _, _, _>): 'Printer =
if level <= LogLevel.INFO then
x.Log fmt
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
warning FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'Printer has been constrained to be type 'unit'.
let l0 = Logger(Console.Error)
l0.Log "foo %d %s %f" 1 "foo" 1.23
let l1 = LevelLogger(Console.Error, LogLevel.INFO)
l1.Info "foo %d %s %f" 1 "foo" 1.23
^^^^^^^^^^^^^^^^^^^^^^
error FS0001: This expression was expected to have type
'unit'
but here has type
''a -> string -> 'b -> unit'
error FS0003: This value is not a function and cannot be applied.
It would be ideal if I could write
member x.Info (fmt: PrintfFormat<'Printer, _, _, _>): 'Printer =
if level <= LogLevel.INFO then x.Log fmt
else Printf.noop fmt
But does there exist such a utility API? Or can we write one?
Workarounds just for "getting things done" that I'm aware of:
fprintfn TextWriter.Null, I believe, still formats all args and can be unnecessarily expensive
kbprintfn with a continuation that conditionally calls writer.WriteLine(sb) has the same issue
In C++ codebase, this kind of dynamic config is often complemented with preprocessor directives (#if ...), like, enabling TRACE level only under -DDEBUG; but I don't know if we can write an ergonomic API with them in F#.
Also, PrintfFormat is always allocated out of a format string anyways, then the "no-op" API can never be a real no-op? But I'm hoping it might still be much light-weight than TextWriter.Null, if that's ever possible.
Ahhh why is PrintfImpl internal??
https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/printf.fs
Update: My attempts so far
https://sharplab.io/#gist:70dd6f915ba14f36c122f601732af1c1
LevelLogger0 doesn't type check, and my understanding is that both LevelLogger1 and 2 would waste CPU & RAM in logger.Trace "%A" (Array.zeroCreate<double> 1_000_000_000) even when the current threshold is INFO.
I tried the same a time ago and did not find a solution.
Meanwhile string interpolation was added and I find it better at all ends over F#s safe but (as we see here a bit tricky) printf. String interpolation is type safe, improves readability and leads to less brackets. Another disadvantage of printf is its behavior during debugging.
I do logging with an extension method that has the Conditional attribute
type ILogger with // this is Serilog.ILogger which I use
[<Conditional("LOG")>]
member o.InformationConditional(s: string) =
o.Information(s)
to be used like
let a = 72
let b = "hello"
logger.InformationConditional($"foo {a} bar {b}")
Keeping with printf you can create the string with sprintf.
The easiest way to get something like your Printf.noop is to use Printf.kprintf, which takes a continuation that is called with the composed string. If you pass ignore as the continuation, this does nothing. However, this unfortunately does not quite work:
member x.Info (fmt: PrintfFormat<'Printer, _, _, _>): 'Printer =
if level <= LogLevel.INFO then x.Log fmt
else Printf.kprintf ignore fmt
This would logically do the trick, but the issue is that the type of fmt expected by kprintf and fprintf differs (in that they have a different state). So, if you want to do this, you will always need to use kprintf and then decide what to do based on the log level inside the continuation:
member x.Info (fmt: PrintfFormat<'Printer, _, _, _>): 'Printer =
fmt |> Printf.kprintf (fun s ->
if level <= LogLevel.INFO then x.Log "%s" s)
Why does printf output Some x for Some x, but <null> for None?
> printfn "%A" (Some 123);;
Some 123
val it : unit = ()
> printfn "%A" None;;
<null>
val it : unit = ()
In compiled code, F# uses the null value to represent the None case of option<'T> for efficiency. You can actually use the same for your own discriminated unions by using the CompilationRepresentationFlags. UseNullAsTrueValue compilation flag (see MSDN documentation).
You can see that this is what's going on by using the Object.ReferenceEquals method:
> let n = None;;
val n : 'a option
> System.Object.ReferenceEquals(n, null);;
val it : bool = true
Why does printfn "%A" just print the internal representation rather than recognizing that this actually represents the None case?
I think the answer is that printing is done dynamically using reflection and so the argument is just converted to a value of type obj at some point. Once you have a value null of type obj, it is not possible to recover what type it was before casting and so you cannot find out that null actually represents None (because null.GetType() fails). Presumably, the printing could use the static type information to get type information that way - but that would probably be more tricky to implement.
This is actually older behavior that won't go away. Tomas' answer is correct for older FSI, but if you install something newer (like .NET Core 3.1 latest, or .NET 5 preview) you'll see with dotnet fsi that None formats as None with your example.
I thought that conversions between F# functions and System.Func had to be done manually, but there appears to be a case where the compiler (sometimes) does it for you. And when it goes wrong the error message isn't accurate:
module Foo =
let dict = new System.Collections.Generic.Dictionary<string, System.Func<obj,obj>>()
let f (x:obj) = x
do
// Question 1: why does this compile without explicit type conversion?
dict.["foo"] <- fun (x:obj) -> x
// Question 2: given that the above line compiles, why does this fail?
dict.["bar"] <- f
The last line fails to compile, and the error is:
This expression was expected to have type
System.Func<obj,obj>
but here has type
'a -> obj
Clearly the function f doesn't have a signature of 'a > obj. If the F# 3.1 compiler is happy with the first dictionary assignment, then why not the second?
The part of the spec that should explain this is 8.13.7 Type Directed Conversions at Member Invocations. In short, when invoking a member, an automatic conversion from an F# function to a delegate will be applied. Unfortunately, the spec is a bit unclear; from the wording it seems that this conversion might apply to any function expression, but in practice it only appears to apply to anonymous function expressions.
The spec is also a bit out of date; in F# 3.0 type directed conversions also enable a conversion to a System.Linq.Expressions.Expression<SomeDelegateType>.
EDIT
In looking at some past correspondence with the F# team, I think I've tracked down how a conversion could get applied to a non-syntactic function expression. I'll include it here for completeness, but it's a bit of a strange corner case, so for most purposes you should probably consider the rule to be that only syntactic functions will have the type directed conversion applied.
The exception is that overload resolution can result in converting an arbitrary expression of function type; this is partly explained by section 14.4 Method Application Resolution, although it's pretty dense and still not entirely clear. Basically, the argument expressions are only elaborated when there are multiple overloads; when there's just a single candidate method, the argument types are asserted against the unelaborated arguments (note: it's not obvious that this should actually matter in terms of whether the conversion is applicable, but it does matter empirically). Here's an example demonstrating this exception:
type T =
static member M(i:int) = "first overload"
static member M(f:System.Func<int,int>) = "second overload"
let f i = i + 1
T.M f |> printfn "%s"
EDIT: This answer explains only the mysterious promotion to 'a -> obj. #kvb points out that replacing obj with int in OPs example still doesn't work, so that promotion is in itself insufficient explanation for the observed behaviour.
To increase flexibility, the F# type elaborator may under certain conditions promote a named function from f : SomeType -> OtherType to f<'a where 'a :> SomeType> : 'a -> OtherType. This is to reduce the need for upcasts. (See spec. 14.4.2.)
Question 2 first:
dict["bar"] <- f (* Why does this fail? *)
Because f is a "named function", its type is promoted from f : obj -> obj following sec. 14.4.2 to the seemingly less restrictive f<'a where 'a :> obj> : 'a -> obj. But this type is incompatible with System.Func<obj, obj>.
Question 1:
dict["foo"] <- fun (x:obj) -> x (* Why doesn't this, then? *)
This is fine because the anonymous function is not named, and so sec. 14.4.2 does not apply. The type is never promoted from obj -> obj and so fits.
We can observe the interpreter exhibit behaviour following 14.4.2:
> let f = id : obj -> obj
val f : (obj -> obj) (* Ok, f has type obj -> obj *)
> f
val it : ('a -> obj) = <fun:it#135-31> (* f promoted when used. *)
(The interpreter doesn't output constraints to obj.)
This active pattern compiles with F# 2.0:
let (|Value|_|) value = // 'a -> 'T option
match box value with
| :? 'T as x -> Some x
| _ -> None
but, in F# 3.0, emits the error:
Active pattern '|Value|_|' has a result type containing type variables that are not determined by the input. The common cause is a [sic] when a result case is not mentioned, e.g. 'let (|A|B|) (x:int) = A x'. This can be fixed with a type constraint, e.g. 'let (|A|B|) (x:int) : Choice = A x'
I tried:
let (|Value|_|) value : 'T option = ...
and:
let (|Value|_|) (value: 'U) = ...
How can it be fixed?
Environments: Visual Studio 2012 (RTM) and FSI v11.0.50727.1
EDIT: Here's a simpler repro:
let (|X|) x = unbox x
There was a bug in the F# 2.0 compiler where the compiler did incorrect analysis and bad code generation for certain Active Patterns with free type variables in the result; a simple repro is
let (|Check|) (a : int) = a, None
//let (|Check|) (a : int) = a, (None : int option)
let check a =
match a with
| Check (10, None) -> System.Console.WriteLine "10"
| Check (20, None) -> System.Console.WriteLine "20"
check 10
check 20
which generates a weird warning at compile-time and compiles into seemingly incorrect code. I am guessing that our attempt to fix this bug (and restrict some crazy cases) in F# 3.0 also broke some legal code as collateral damage of the fix.
I'll file another bug, but for F# 3.0, it sounds like you'll need to use one of the workarounds mentioned in other answers.
I did not install the new version yet, but I agree this looks a bit fishy. I guess there may be a good reason for this restriction, but your example in the other question seems quite compeling.
As a workaround, I think that adding a witness parameter (that is not used, but hints what the type of the result is going to be) could work:
let (|Value|_|) (witness:unit -> 'T) value : 'T option =
match box value with
| :? 'T as x -> Some x
| _ -> None
Of course, this makes the use a bit uglier, because you need to come up with some argument. In the above, I used witness of type unit -> 'T, hoping that the following might compile:
let witness () : 'T = failwith "!"
match box 1 with
| Value witness 1 -> printfn "one"
If that does not work, then you can probably try using witness parameter of type 'T (but then you have to provide an actual function, rather than just a generic function).
for the sake of completeness, one more workaround:
type Box<'R> = Box of obj
let (|Value|_|) ((Box x) : Box<'R> ) : 'R option =
match x with
| :? 'R as x -> Some x
| _ -> None
let check t =
match Box t with
| Value 1 -> printfn "one"
| Value 2 -> printfn "two"
check 1 // one
check 2 // two
however it still will suffer from the problem mentioned by #kvb in another thread. Personally I'll prefer #kvb's version with parameterized active pattern.
See my answer to your other question for some thoughts on how to work around the issue and one reason that such active patterns might be undesirable. I'm not sure whether the breaking change was intended.
Alright... this question is more or less related to one I've asked earlier today (F# - "Not a valid property expression"), which #Tomas Petricek answer perfectly - however it seems my lack of knowledge and the DLR, requires me to ask once again (been trying for quite a while to mix something up without luck at all).
I'm having this function (stolen from the example Tomas gave in the previous thread):
let hasSeq (e:Expr<'a -> seq<'b>>) =
match e with
| Patterns.Lambda(v, Patterns.PropertyGet(Some instance, propInfo, [])) ->
printfn "Get property %s of %A" propInfo.Name instance
// TODO: Use 'Expr.Lambda' & 'Expr.PropGet' to construct
// an expression tree in the expected format
| _ -> failwith "Not a lambda!"
How would I reconstruct the expression tree with Expr.Lambda and Expr.PropGet? - I need to make the seq<'b> to ICollection<'b> instead, so that the expression in the end is like: 'a -> ICollection<'b>
Well, if you've already decomposed quotation, then maybe you can create required expression tree by yourself without ToLinqExpression from PowerPack?
type A =
member this.Values : int[] = failwith ""
open Microsoft.FSharp.Quotations
type F<'T, 'R> = System.Func<'T, 'R>
type E = System.Linq.Expressions.Expression
type IC<'T> = System.Collections.Generic.ICollection<'T>
let toLinqPropGet (e : Expr<'T -> #seq<'R>>) =
match e with
| Patterns.Lambda(_, Patterns.PropertyGet(Some _, pi, []))
when typeof<IC<'R>>.IsAssignableFrom(pi.PropertyType) ->
let p = E.Parameter(typeof<'T>)
let propGet = E.Property(p :> E, pi)
E.Lambda<F<'T, IC<'R>>>(propGet, p) :> E
| _ -> failwith "PropGet expected"
let r = toLinqPropGet <# fun (x : A) -> x.Values #>
printfn "%A" r
This isn't going to work.
You want to build a quotation of type Entity -> ICollection<Something> and you have a quotation of type Entity -> seq<Something>. However, entity framework only supports simple lambda functions that get some property (e.g. x => x.SomeProperty).
If your Entity has only a property Foo of type seq<Something>, then there is no way you could build a quotation with the required structure (lambda that just gets a property) and of the required type (Entity -> ICollection<Something>), because the type of the property doesn't match!
What I suggested earlier is to change the entity to also have a property FooInternal of the right type (ICollection<Something>). Then you could build a quotation x => x.FooInternal, which would work fine with entity framework.
Perhaps you could give more details about what you're actually trying to achieve? We can try to help with technical details, but it seems that you may need to adjust your design a bit (to actually work with the ICollection type as required by EF).