I am trying to use F# as a REPL and scripting which uses C# library. When I evaluate an object in REPL, it prints its internal structure:
> <expression>;;
val it: <type> =
<subtype> {<prop> = <value>;
...
<prop> = <value>;}
Then I am writing a script with the same expression and want it to print same output. But I cannot find any print function which would do it. The closest I could find is printfn "%O" which uses ToString() method, which is not defined in my case and just prints the object type.
This seems to be a simple question but I cannot find it answered here or anywhere in Google.
How to generate the F# type signature similar to FSI in my own code? seems to be focused on type, and I basically need rather pretty-printed value.
PS: seems like it is code which is internal to fsi.exe. See fsi.fs and sformat.fs sources. I tried to invoke them through reflection, but simple Internal.Utilities.StructuredFormat.any_to_string(value) printed just a type. Would still be nice if anybody knows how to invoke it correctly, but for time being I decided not to spend more efforts on it.
I just had the same issue, but in my case, printfn "%A" gave exactly the same result as what I see in F# Interactive (bar the indentation):
For a list:
> let l = [(2,"a")];;
val l : (int * string) list = [(2, "a")]
> printfn "%A" l;;
[(2, "a")]
For a record:
> type R = { A: string; B: int };;
type R =
{A: string;
B: int;}
> let r = { A = "Foo"; B = 1 };;
val r : R = {A = "Foo";
B = 1;}
> printfn "%A" r;;
{A = "Foo";
B = 1;}
For a non-F# datatype:
> let u = UriBuilder("http", "bar", 80);;
val u : UriBuilder = http://bar:80/
> printfn "%A" u;;
http://bar:80/
Related
Can somebody help me with article of Tomas Petricek: http://tomasp.net/blog/fsharp-dynamic-lookup.aspx/#dynfslinks?
The problem is that it is severely outdated. I understand that namespaces
open Microsoft.FSharp.Quotations.Typed
open Microsoft.FSharp.Quotations.Raw
are gone. So I removed the openings. But there are still errors. "Typed" is not defined. "RecdGet" is not defined. And I suspect they are not the last. I'm trying to prove to my boss that F# is good to use for database normalization. Dynamic lookup of fields would really helped me to deal with similarly named fields having different prefixes.
There is also post of Tomas on fpish: https://fpish.net/topic/None/57493, which I understand predates the article
Here's a rough equivalent:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
type DynamicMember<'t,'u> = Expr<'t -> 'u>
let getValueReader (expr:DynamicMember<'recdT, 'fieldT>) =
// Match the quotation representing the symbol
match expr with
| Lambda(v, PropertyGet (Some (Var v'), pi, [])) when v = v' ->
// It represents reading of the F# record field..
// .. get a function that reads the record field using F# reflection
let rdr = Reflection.FSharpValue.PreComputeRecordFieldReader pi
// we're not adding any additional processing, so we just
// simply add type conversion to the correct types & return it
((box >> rdr >> unbox) : 'recdT -> 'fieldT)
| _ ->
// Quotation doesn't represent symbol - this is an error
failwith "Invalid expression - not reading record field!"
type SampleRec = { Str : string; Num : int }
let readStrField = getValueReader <# fun (r : SampleRec) -> r.Str #>
let readNumField = getValueReader <# fun (r : SampleRec) -> r.Num #>
let rc = { Str = "Hello world!"; Num = 42 }
let s, n = readStrField rc, readNumField rc
printfn "Extracted: %s, %d" s n
Learning F# as part of my course, and can do some cool things, but something has been bugging me, whenever I use the val keyword, I get an error. I think it could be due to not declaring something in script, but I don't really know.
module Prime
#light
let nums = [1; 2; 3; 4; 5];;
val nums : list<int>
let rec sum list =
match list with
| h::tail -> (sum tail) + h
| [] -> 0
val sum : list<int> -> int
I get (line 5):
Error 1 Unexpected keyword 'val' in definition . Expected incomplete structured construct at or before this point or other token
Any ideas?
The val keyword in F# (unlike 'val' in ML) is used to declare a field in a class or structure type without initializing it.
http://msdn.microsoft.com/en-us/library/dd469494.aspx
if you want to define mutable value in the Module you can use
let mutable...
By the way, if you define the value with the same name (like 'nums') twice or more times then the effective value for the compiler will be latest defined in the scope.
So actually, I had misread the coursework set out, annoyingly the papers use val to define what the expected output of the function is, as opposed to using it as the keyword it is meant to be. Hence my confusion and lots of head scratching.
This looks like F# interactive output mixed in with code.
If I type this into FSI:
let nums = [1; 2; 3; 4; 5];;
The output is
val nums : int list = [1; 2; 3; 4; 5]
Note that ;; is where FSI parses and runs input. You wouldn't have this in non-interactive code. The output might differ because of an older version or editing, but nontheless, it doesn't belong in code.
Coincidentally, val is also a rarely used F# keyword for explicit fields. Hence the strange error message.
The val keyword is used to declare a field ; it must be used inside a type definition (class or structure). Since in your code the variable nums is already defined and as the list type inferred by F# type inference engine, there is no need for your val line.
An example of val keyword usage is (from msdn) :
type MyType() =
let mutable myInt1 = 10
[<DefaultValue>] val mutable myInt2 : int
[<DefaultValue>] val mutable myString : string
member this.SetValsAndPrint( i: int, str: string) =
myInt1 <- i
this.myInt2 <- i + 1
this.myString <- str
printfn "%d %d %s" myInt1 (this.myInt2) (this.myString)
Given an F# record:
type R = { X : string ; Y : string }
and two objects:
let a = { X = null ; Y = "##" }
let b = { X = "##" ; Y = null }
and a predicate on strings:
let (!?) : string -> bool = String.IsNullOrWhiteSpace
and a function:
let (-?>) : string -> string -> string = fun x y -> if !? x then y else x
is there a way to use F# quotations to define:
let (><) : R -> R -> R
with behaviour:
let c = a >< b // = { X = a.X -?> b.X ; Y = a.Y -?> b.Y }
in a way that somehow lets (><) work for any arbitrary F# record type, not just for R.
Short: Can quotations be used to generate F# code for a definition of (><) on the fly given an arbitrary record type and a complement function (-?>) applicable to its fields?
If quotations cannot be used, what can?
You could use F# quotations to construct a function for every specific record and then compile it using the quotation compiler available in F# PowerPack. However, as mentioned in the comments, it is definitely easier to use F# reflection:
open Microsoft.FSharp.Reflection
let applyOnFields (recd1:'T) (recd2:'T) f =
let flds1 = FSharpValue.GetRecordFields(recd1)
let flds2 = FSharpValue.GetRecordFields(recd2)
let flds = Array.zip flds1 flds2 |> Array.map f
FSharpValue.MakeRecord(typeof<'T>, flds)
This function takes records, gets their fields dynamically and then applies f to the fields. You can use it to imiplement your operator like this (I'm using a function with a readable name instead):
type R = { X : string ; Y : string }
let a = { X = null ; Y = "##" }
let b = { X = "##" ; Y = null }
let selectNotNull (x:obj, y) =
if String.IsNullOrWhiteSpace (unbox x) then y else x
let c = applyOnFields a b selectNotNull
The solution using Reflection is quite easy to write, but it might be less efficient. It requires running .NET Reflection each time the function applyOnFields is called. You could use quotations to build an AST that represents the function that you could write by hand if you knew the record type. Something like:
let applyOnFields (a:R) (b:R) f = { X = f (a.X, b.X); Y = f (a.Y, b.Y) }
Generating the function using quotations is more difficult, so I won't post a complete sample, but the following example shows at least a part of it:
open Microsoft.FSharp.Quotations
// Get information about fields
let flds = FSharpType.GetRecordFields(typeof<R>) |> List.ofSeq
// Generate two variables to represent the arguments
let aVar = Var.Global("a", typeof<R>)
let bVar = Var.Global("b", typeof<R>)
// For all fields, we want to generate 'f (a.Field, b.Field)` expression
let args = flds |> List.map (fun fld ->
// Create tuple to be used as an argument of 'f'
let arg = Expr.NewTuple [ Expr.PropertyGet(Expr.Var(aVar), fld)
Expr.PropertyGet(Expr.Var(bVar), fld) ]
// Call the function 'f' (which needs to be passed as an input somehow)
Expr.App(???, args)
// Create an expression that builds new record
let body = Expr.NewRecord(typeof<R>, args)
Once you build the right quotation, you can compile it using F# PowerPack. See for example this snippet.
Perhaps a silly question, but why does the return value from unbox appear (in my F# Interactive session) to be typed as obj instead of the concrete type int? As far as I can understand (trying to apply existing knowledge from C#) if it's typed as obj then it's still boxed. Example follows:
> (unbox<int> >> box<int>) 42;;
val it : obj = 42
> 42;;
val it : int = 42
Function composition (f >> g) v means g (f (v)), so you're actually calling box<int> at the end (and the call to unbox<int> is not necessary):
> box<int> (unbox<int> 42);;
val it : obj = 42
> box<int> 42;;
val it : obj = 42
The types are box : 'T -> obj and unbox : obj -> 'T, so the functions convert between boxed (objects) and value types (int). You can call unbox<int> 42, because F# automatically inserts conversion from int to obj when calling a function.
On a related note: such a method is actually quite useful. I use it to deal with "the type of an object expression is equal to the initial type" behavior.
let coerce value = (box >> unbox) value
type A = interface end
type B = interface end
let x =
{ new A
interface B }
let test (b:B) = printf "%A" b
test x //doesn't compile: x is type A (but still knows how to relax)
test (coerce x) //works just fine
I guess it's now Object.ToString() but I'm unsure... Thanks!
I think the only way to get any_to_string functionality is with the "%A" formatter. The warning tells you this.
let any_to_string = sprintf "%A"
This does not invoke .ToString(). For 'simple' types like lists the .ToString() already yields a good representation. But when using your own custom types, the %A formatter is much more useful. For instance, in case of tree structures it walks along the tree.
If you do want to invoke .ToString() on an object, you can use the '%O' formatter.
Example:
type Tree = Node of Tree * Tree | Leaf
let myTree = Node(Node(Leaf,Leaf),Node(Leaf,Node(Leaf,Leaf)))
and in FSI:
> myTree.ToString();;
val it : string = "FSI_0002+Tree+Node"
> sprintf "%O" myTree;;
val it : string = "FSI_0002+Tree+Node"
> sprintf "%A" myTree;;
val it : string = "Node (Node (Leaf,Leaf),Node (Leaf,Node (Leaf,Leaf)))"
you can use sprintf:
let a = [1;2;3]
let b = sprintf "%A" a
What about the string function?
> string [1..3];;
val it : string = "[1; 2; 3]"