F# - What's the "it" keyword? - f#

I am a newb to F#, just began learning it this afternoon.
What I've noticed is that when getting type info via the fsi, I get the following info:
val it : (char list -> string -> string list) = <fun:clo#0>
If I understand correctly, the (char list -> string -> string list) means that the function takes a list of char and returns a function that takes a string and returns a list of string.
However, I don't understand the usage of the "it".
Thanks for any info!

In the F# interactive command line, "it" is an identifier that gets bound to the last expression evaluated. For example:
> let a = 5;;
val a : int = 5
> a;;
val it : int = 5
> it;;
val it : int = 5
>

It's not a keyword. Here's the F# keyword list.
Info on the val keyword:
The val keyword is used to declare a field in a class or structure type without initializing it. Fields declared in this manner are called explicit fields.
[ static ] val [ mutable ] [ access-modifier ] field-name : type-name
So the it normally is the field name.
In the interactive console it's the return value (val) (the name is irrelevant, they just call it "it"):
> System.Console.ReadLine();;
Test
val it : string = "Test"
> it;;
val it : string = "Test"

"it" is sometimes used as a placeholder argument name (for example, arguments to anonymous blocks). It's (no pun intended ;-) just a convention AFAIK.

Related

F# list of discriminated union sub-types

I want to present the user with a list of 'FParsec parsers'-plus-'test data' from which they can interactively select and see the results of the parser run on the supplied text.
Specifically, am trying to collect my parser tests in a list of records of this type:
type FUNCTION_TEST =
| XELEMENT_MATCH of label : string * func : Parser<(int * string), unit> * data : string
| XKEYVALUE_MATCH of label : string * func : Parser<(string * string), unit> * data : string
let testable_parsers = [( "xElement", xElement, xElement_text3)
( "xKeyValue", xKeyValue, xKeyValue_text)]
xKeyValue above throws the error...
val xKeyValue: Parser<(string * string), unit>
Full name CustomParser.xKeyValue
FS0001:the type '(int * string)' does not match the type 'string * string'
I want the user to see and choose a label string and see the results of running the parser.
I understand that the parser xElement : Parser<int * string, unit> does not match parser xKeyValue : Parser<(string * string), unit>. Both sub-types are part of the FUNCTION_TEST discriminated union BUT I cannot put the parsers in the same list because their sub-types (XELEMENT_MATCH versus XKEYVALUE_MATCH) disagree.
I wanted to handle this using a match ... with over the discriminated union.
I am new to F# and FParsec and out of elegant ideas. Do I have to hard-code a menu with do! and printfs?
How do experienced F# and FParsec developers allow users to select from a menu of options of different types?
I think the best approach would be to restructure your data so that you keep all the common things (label and data) in a record, together with a value representing the function - which can then be a discriminated union with a case for each type:
type Function =
| Element of Parser<(int * string), unit>
| KeyValue of Parser<(string * string), unit>
type Test =
{ Label : string
Data : string
Function : Function }
Now you can create a list of Test values, which you can easily iterate over to get all the labels & data:
let testableParsers =
[ { Label = "xElement"; Function = Element(xElement); Data = xElement_text3 }
{ Label = "xKeyValue"; Function = KeyValue(xKeyValue); Datta = xKeyValue_text } ]
You will still need to use pattern matching when you want to run a specific Function, because this will have to handle the different values you get as a result, but you won't need pattern matching elsewhere.
I'm a bit confounded by the FUNCTION_TEST type. It looks like you're never using the type or any of its constructors, and if so, why did you define that type in the first place?
After pondering the possible motives you may have had, it looks like perhaps you wanted the testable_parsers list to contain values of the FUNCTION_TEST type so that you can later match on them?
If that is the case, then what you have is not what you intended: the list that you have constructed contains tuples of three values.
In order to construct values of the FUNCTION_TEST type, you need to apply its constructors:
testableParsers = [
XELEMENT_MATCH ("xElement", xElement, xElement_text3)
XKEYVALUE_MATCH ("xKeyValue", xKeyValue, xKeyValue_text)
]
But if your only purpose is to present a choice to the user, then I wouldn't even bother with a special type to represent the options. You can just pair labels with functions to be called when the user chooses the label:
testableParsers = [
"xElement", fun() -> runParser xElement xElement_text3
"xKeyValue", fun() -> runParser xKeyValue xKeyValue_text
]
This way you don't have to do a match on the values of FUNCTION_TEST either, just call the function.

Discriminated Union label to string

given the following Discriminated Union:
type A = B of string | C of int
How can I get the constructor B name?
A.B.ToString()
// would return something like:
val it : string = "FSI_0045+it#109-19"
// when I desire
val it : string = "B"
for example with this type it works:
type D = E | F
D.E.ToString();;
val it : string = "E"
I normally get the string name of an instance of the DU with
let stringFromDU (x: 'a) =
match FSharpValue.GetUnionFields(x, typeof<'a>) with
| case, _ -> case.Name
But in this case, I do not have an instance, I just want to serialize the label name.
If you enable the latest language version, e.g. by passing --langversion:preview to FSI or setting
<PropertyGroup>
<LangVersion>preview</LangVersion>
</PropertyGroup>
in your .fsproj, the following will work:
type A = B of int
let n = nameof A.B
Note: with F# 5 this will be supported out of the box :-)
You're using FSharpValue from FSharp.Reflection namespace in your example. Note that there's another class in that library for handling scenarios where you want to work with types only, FSharpType.
let cases = FSharpType.GetUnionCases(typeof<A>)
Outside of unions, it also provides helpers for other operations on F# native types.

Specifying a generic parameter in a double list in F#

I am creating a function in F# which is given a list of lists, and which returns true, if all lists are of the same length, except if this length is 0.
I want to specify that the entries of the inner list can be a generic type 'T, so I was going for
let properTable (input : list list<'T>) : bool =
let lengths = set ([for i in 0..(input.Length-1) -> input.[i].Length])
not (lengths.Contains(0)) && lengths.Count = 1
When pasting this function into F# interactive, I get the error message:
stdin(148,35): error FS0010: Unexpected type application in pattern. Expected ')' or other token.
If I replace the type the type of input with int list list, the function works, but I'd like any type, not just an int.
I can get it to work with only a single list, as in
let testSingleList (input : list<'T>) : bool =
input.Length > 0
How can I accomplish a similar construction, but for a list of lists?
You're mixing two different "styles" of type annotation.
Using either
'T list list
or
List<List<'T>>
should work.

Can I get the inferred type of a value, without the contents, in F# Interactive?

When a value is created in the F# Interactive console the inferred type and contents of the value are displayed.
How can I, at a later date, redisplay the inferred type without showing all the contents?
For example, I have an array, mydata of 1000 items. Typing mydata into the F# Interactive console will display the type, but also the contents of the array.
How about using printfn with the type like so:
F# Interactive for F# 3.1 (Open Source Edition)
Freely distributed under the Apache 2.0 Open Source License
For help type #help;;
>
val mya : int [] = [|3; 2; 5; 6; 7; 8|]
> printfn "%A" (mya.GetType());;
System.Int32[]
val it : unit = ()
You can shorten the typing required by using a little utility function:
let pm v = printfn "%A" (v.GetType())
The you can use as follows:
> pm mya;;
System.Int32[]
val it : unit = ()
"pm" stands for "print me". Call it whatever you want :)
Another approach if you don't like the type names from GetType() is just to cause an error with the value you want to evaluate. That will give you a more friendly F# type name (if you don't mind ignoring the error of course). For instance on a list you could do:
>
val myl : string list = ["one"; "two"]
> printfn myl;;
Script.fsx(195,9): error FS0001: The type 'string list' is not compatible with the type 'Printf.TextWriterFormat<'a>'
Note the type string list between the ''
Lastly you can use: (MSDN)
fsi.ShowDeclarationValues <- false
But this only silences the initial evaluation.
Unquote has an extension property for types:
> let mydata = [|Some([42])|];;
val mydata : int list option [] = [|Some [42]|]
> mydata.GetType().FSharpName;;
val it : string = "option<list<int>>[]"

Unexpected keyword 'val' in definition

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)

Resources