F# - printfn Guid - f#

I have following printing example in F#
for row in data.Rows do
printfn "Example: (%s)" row.A
But I received this error
Script1.fsx(15,67): error FS0001: This expression was expected to have
type
string but here has type
Guid
I didn't find any example of printing of Guid type.
I tried apply ToString() method to row.A but it is not working as well

There are two options here:
for row in data.Rows do
printfn "Example: (%s)" (row.A.ToString())
or
for row in data.Rows do
printfn "Example: (%A)" row.A
Here the %A can be used for any type and the compiler will automatically print it for you

You can use %A for a Guid, like this:
printfn "Example: (%A)" row.A
When using %s, the type must be a string.
The MSDN Documentation has more information about which format type to use and how it behaves.

In addition to the answers already given, it's worth noting that Guid also supports an overload of ToString, giving you the option to control how the GUID string is formatted.
You could, for example, write it out like this:
printfn "Example: (%s)" (row.A.ToString "n")
if you want to omit the hyphens (Example: (78e6fb89dc5045988d445c4d8aef4e28)).
Or you could use stringf for this, if you want an alternative with pipes instead of parentheses:
row.A |> stringf "n" |> printfn "Example: (%s)"
or if you don't need the formatting option:
row.A |> string |> printfn "Example: (%s)"

Related

How can I wrap sprintf + a call into a single function, and have two signatures, in F#?

I have a function that takes a string and sends it to a terminal:
Print: string -> unit
it is passed to several modules that do this, to simplify the syntax
// printing
let print = settings.Print
and then it's used like that:
print "hello"
print (sprintf "the time is %A" DateTime.UtcNow)
my question is: Can I make two functions, with the same name but two signatures, so I could use it to either print a string, or a sprintf, then print the string.
for example:
print "hello"
print "the time is %A" DateTime.UtcNow
Is this possible? the goal is to simplify the syntax as a lot of code is peppered with info being sent to the terminal (which is currently a Telegram channel)
You can use kprintf for this:
let myPrint s = printfn "My print: %s !" s
let print x = Printf.kprintf myPrint x
print "%d" 1
print "aaaa"
print "%s %s" "b" "c"
There are some examples here and here.
I couldn't find kprintf documentation, so I'm not sure that this usage is correct, but it produces the correct result for me. Another possible candidate is ksprintf, which also produces the same result.
You can use the same signature as sprintf:
let print (format : Printf.StringFormat<'T>) =
sprintf format
|> dosomethingElse
and you can use it as you want:
print "hello"
print "the time is %A" DateTime.UtcNow

Why does F# not like the type ('a list list) as input?

*I edited my original post to include more info.
I'm working on an F# assignment where I'm supposed to create a function that takes an "any list list" as input and outputs an "any list". It should be able to concatenate a list of lists into a single list.
Here's what my function looks like:
let llst = [ [1] ; [2;3] ; ['d';'e';'f'] ]
let concat (llst:'a list list) : 'a list =
List.concat llst
List.iter (fun elem -> printf "%d " elem) concat
This solution more or less copied directly from microsofts example of using the List.concat function, the only exception being the specification of input/output types.
When i run the code i get this error:
concat.fsx(7,43): error FS0001: This expression was expected to have type
''a list'
but here has type
''b list list -> 'b list'
So it appears that concat is turning my llst into a character list, which i don't understand.
Can anyone help me understand why I'm getting this type error and how I can write a function that takes the types that I need?
The problem is somewhere in your implementation of the concat function. It is hard to say where exactly without seeing your code, but since this is an assignment, it is actually perhaps better to explain what the error message is telling you, so that you can find the issue yourself.
The error message is telling you that the F# type inference algorithm found a place in your code where the actual type of what you wrote does not match the type that is expected in that location. It also tells you what the two mismatching types are. For example, say you write something like this:
let concat (llst:'a list list) : 'a list =
llst
You will get the error you are getting on the second line, because the type of llst is 'a list list (the compiler knows this from the type annotation you give on line 1), but the expected type is the same as the result type of the function which is 'a list - also specified by your type annotation.
So, to help you find the issue - look at the exact place where you are getting an error and try to infer why compiler thinks that the actual type is 'a list list and try to understand why it expects 'a list as the type that should be in this place.
This is correct:
let concat (llst:'a list list) : 'a list =
List.concat llst
However, it's really equivalent to let concat = List.concat
This, however, doesn't compile, the elements of the lists need to be of the same type:
let llst = [ [1] ; [2;3] ; ['d';'e';'f'] ]
This also is problematic:
List.iter (fun elem -> printf "%d " elem) concat
List.iter has two arguments and the second one needs to be a List. However in your case you are (as per compiler error) providing your concat function which is a a' List List -> a' List.
What I suspect you meant to do, is apply the concat function to your llist first:
List.iter (fun elem -> printf "%d " elem) (concat llist)
// or
llist
|> concat
|> List.iter (fun elem -> printf "%d " elem)
However, all of this is perhaps missing the point of the exercise. What perhaps you need to do is implement some simple recursion based on the empty / non-empty state of your list, ie. fill in the blanks from here:
let rec myconcat acc inlist =
match inlist with
| [] -> ??
| elt :: tail -> ??

How to print a bigint in F#?

I am trying to find out how to print out the value of a bigint or System.Numerics.BigInteger in F#. I have found a site here that attempts to explain how to do this, but in the Visual Studio editor, it is flagged as an error. So far, I am just trying something simple like:
printfn "bigInt: %A " 123456789I
But that gets flagged as:
Why does this not work? How can I print out a bigint?
Code:
[<EntryPoint>]
let main =
printfn "bigInt: %A " 123456789I
If you are using an explicit entry point, main needs to accept a single string[] argument and return int. Your sample code is missing both of those requirements. Your printfn line is fine.
[<EntryPoint>]
let main (argv : string[]) =
printfn "bigint %A" 12345I
0

printfn "%A" "c" using F#

By running printfn "%A" "c", I get "c".
By running printfn "%s" "c", I get c.
Why the difference? The same goes for char.
The %A specifier tries to hint at object types - the "c" is it trying to show it is a string. When you do %s the compiler knows you want to print a string so it doesn't print the quotes
Because printfn "%A" uses reflection, it displays results the same as values automatically printed out by F# Interactive. On the other hand, %s is for strings only, and it shows contents of strings.
The generic case of "%s" is "%O" when ToString methods are used. The %A specifier is slow, but helpful for structural types and types without overridden ToString methods.

Printing F# discriminated union

I am writing a F# program which parses a string into a AST type which is a discriminated union.
When I use fsi (on Mono + Mac OS X) to run my code, the AST is printed out in a nice format. But when I use printfn "%s" <| ast.ToString() I get something like FSI_0002.Absyn+clazz. Writing a ToString method for all the discriminated union types would be a big chore.
How do I make the value print the way fsi does it?
Have you tried printfn "%A" ast? The %A specifier takes into consideration the StructuredFormatDisplayAttribute[MSDN], if present.
To convert a discriminated union into a string, you should use sprintf "%A" ast instead of ast.ToString().
If you want Enum.GetName, you can use Microsoft.FSharp.Reflection namespace. See What is the Enum.GetName equivalent for F# union member?.
In addition to Daniel's comment, here is a good blog article explaining how to format it in whatever way you'd wish:
http://blogs.msdn.com/b/dsyme/archive/2010/01/08/some-tips-and-tricks-for-formatting-data-in-f-interactive-and-a-in-sprintf-printf-fprintf.aspx (web.archive.org)

Resources