Disable compiler warnings per line - f#

Is it possible to disable compiler warnings for specific lines?
In C#, this works:
[Obsolete]
class Old { }
#pragma warning disable 612
var oldWithoutWarning = new Old();
#pragma warning restore 612
var oldWithWarning = new Old();
This would be very useful for disabling incomplete pattern matches warnings, especially when a function accepts a particular case of a DU.

No, the warnings are turned off per-file (or possibly 'from here to the bottom of the file') when using #nowarn. (Or per compilation/project when using project properties / --nowarn command-line.)

Since everything is an expression in F# it's not hard to pull out a line or a part of a line and put it in it's own file.
Example of my issue, where :: pattern matching warned about empty list possiblity, but my state passed to Seq.fold always has a list with at least one item.
module FoldBookmarks
#nowarn "25"
let foldIntoBookmarks: (string * int * int) seq -> XamlReport.PDF.Bookmark seq =
Seq.fold (fun ((tl,pl,acc)::l) (t,p,_) -> (t,acc,p+acc)::((tl,pl,acc)::l)) [("",0,1)]
>> Seq.map(fun (x,y,_) -> PDF.Bookmark(Title=x, PageNumber= System.Nullable(y)))

Related

FsCheck: Override generator for a type, but only in the context of a single parent generator

I seem to often run into cases where I want to generate some complex structure, but a special variation with a member type generated differently.
For example, consider this tree
type Tree<'LeafData,'INodeData> =
| LeafNode of 'LeafData
| InternalNode of 'INodeData * Tree<'LeafData,'INodeData> list
I want to generate cases like
No internal node is childless
There are no leaf-type nodes
Only a limited subset of leaf types are used
These are simple to do if I override all generation of a corresponding child type.
The problem is that it seems register is inherently a thread-level action, and there is no gen-local alternative.
For example, what I want could look like
let limitedLeafs =
gen {
let leafGen = Arb.generate<LeafType> |> Gen.filter isAllowedLeaf
do! registerContextualArb (leafGen |> Arb.fromGen)
return! Arb.generate<Tree<NodeType, LeafType>>
}
This Tree example specifically can work around with some creative type shuffling, but that's not always possible.
It's also possible to use some sort of recursive map that enforces assumptions, but that seems relatively complex if the above is possible. I might be misunderstanding the nature of FsCheck generators though.
Does anyone know how to accomplish this kind of gen-local override?
There's a few options here - I'm assuming you're on FsCheck 2.x but keep scrolling for an option in FsCheck 3.
The first is the most natural one but is more work, which is to break down the generator explicitly to the level you need, and then put humpty dumpty together again. I.e don't rely on the type-based generator derivation so much - if I understand your example correctly that would mean implementing a recursive generator - relying on Arb.generate<LeafType> for the generic types.
Second option - Config has an Arbitrary field which you can use to override Arbitrary instances. These overrides will take effect even if the overridden types are part of the automatically generated ones. So as a sketch you could try:
Check.One ({Config.Quick with Arbitrary = [| typeof<MyLeafArbitrary>) |]) (fun safeTree -> ...)
More extensive example which uses FsCheck.Xunit's PropertyAttribute but the principle is the same, set on the Config instead.
Final option! :) In FsCheck 3 (prerelease) you can configure this via a new (as of yet undocumented) concept ArbMap which makes the map from type to Arbitrary instance explicit, instead of this static global nonsense in 2.x (my bad of course. seemed like a good idea at the time.) The implementation is here which may not tell you all that much - the idea is that you put an ArbMap instance together which contains your "safe" generators for the subparts, then you ArbMap.mergeWith that safe map with ArbMap.defaults (thus overriding the default generators with your safe ones, in the resulting ArbMap) and then you use ArbMap.arbitrary or ArbMap.generate with the resulting map.
Sorry for the long winded explanation - but all in all that should give you the best of both worlds - you can reuse the generic union type generator in FsCheck, while surgically overriding certain types in that context.
FsCheck guidance on this is:
To define a generator that generates a subset of the normal range of values for an existing type, say all the even ints, it makes properties more readable if you define a single-case union case, and register a generator for the new type:
As an example, they suggest you could define arbitrary even integers like this:
type EvenInt = EvenInt of int with
static member op_Explicit(EvenInt i) = i
type ArbitraryModifiers =
static member EvenInt() =
Arb.from<int>
|> Arb.filter (fun i -> i % 2 = 0)
|> Arb.convert EvenInt int
Arb.register<ArbitraryModifiers>() |> ignore
You could then generate and test trees whose leaves are even integers like this:
let ``leaves are even`` (tree : Tree<EvenInt, string>) =
let rec leaves = function
| LeafNode leaf -> [leaf]
| InternalNode (_, children) ->
children |> List.collect leaves
leaves tree
|> Seq.forall (fun (EvenInt leaf) ->
leaf % 2 = 0)
Check.Quick ``leaves are even`` // output: Ok, passed 100 tests.
To be honest, I like your idea of a "gen-local override" better, but I don't think FsCheck supports it.

Why does F# Interactive behave differently than compiler with regards to immutable value definition?

In reading John Palmer's answer to What is the difference between mutable values and immutable value redefinition?, John notes that
This sort of redefinition will only work in fsi.
In working with F# Interactive (fsi) I guess I subconsciously knew it, but never paid attention to it.
Now that it is apparent, why the difference?
More specifically please explain how the internals are different between fsi and the compiler such that this occurs by design or result of differences?
If the answer can elaborate on the internal structures that hold the bindings that would be appreciated.
The semantics are consistent with the way FSI compiles interactive submissions to an FSI session: each interactive submission is compiled as module which is open to subsequent interactive submissions.
The following is close to what FSI actual does and illustrates how let binding shadowing works across interactive submissions:
FSI Submission #1: let x = 1;;
module FSI_1 =
let x = 1
open FSI_1 //FSI_1.x is now bound to 1 and available at the top level
FSI Submission #2: let x = 2;;
module FSI_2 =
let x = 2
open FSI_2 //FSI_1.x is now shadowed by FSI_2.x which is bound to 2 and available at the top level
You can see the actual details how how the dynamic FSI assembly is compiled by using reflection on the FSI_ASSEMBLY assembly within the FSI app domain. Each interactive submission is literally emitted as a module (.NET class) with the naming pattern FSI_####. FsEye uses these facts to discover the state of FSI top-level bindings: https://code.google.com/p/fseye/source/browse/tags/2.0.1/FsEye/Fsi/SessionQueries.fs#24
The key takeaway in regard to #JohnPalmer's answer is that top-level FSI definitions cannot be mutated, when they are "redefined" they are merely being shadowed. We can show this as follows:
> let x = 1;; //our original definition of x
val x : int = 1
> let f () = x;; //capture x
val f : unit -> int
> let x = 2;; //shadow our original definition of x
val x : int = 2
> f();; //returns the original x value, which is still 1 rather than 2
val it : int = 1

File transform in F#

I am just starting to work with F# and trying to understand typical idoms and effective ways of thinking and working.
The task at hand is a simple transform of a tab-delimited file to one which is comma-delimited. A typical input line will look like:
let line = "#ES# 01/31/2006 13:31:00 1303.00 1303.00 1302.00 1302.00 2514 0"
I started out with looping code like this:
// inFile and outFile defined in preceding code not shown here
for line in File.ReadLines(inFile) do
let typicalArray = line.Split '\t'
let transformedLine = typicalArray |> String.concat ","
outFile.WriteLine(transformedLine)
I then replaced the split/concat pair of operations with a single Regex.Replace():
for line in File.ReadLines(inFile) do
let transformedLine = Regex.Replace(line, "\t",",")
outFile.WriteLine(transformedLine)
And now, finally, have replaced the looping with a pipeline:
File.ReadLines(inFile)
|> Seq.map (fun x -> Regex.Replace(x, "\t", ","))
|> Seq.iter (fun y -> outFile.WriteLine(y))
// other housekeeping code below here not shown
While all versions work, the final version seems to me the most intuitive. Is this how a more experienced F# programmer would accomplish this task?
I think all three versions are perfectly fine, idiomatic code that F# experts would write.
I generally prefer writing code using built-in language features (like for loops and if conditions) if they let me solve the problem I have. These are imperative, but I think using them is a good idea when the API requires imperative code (like outFile.WriteLine). As you mentioned - you started with this version (and I would do the same).
Using higher-order functions is nice too - although I would probably do that only if I wanted to write data transformation and get a new sequence or list of lines - this would be handy if you were using File.WriteAllLines instead of writing lines one-by-one. Although, that could be also done by simply wrapping your second version with sequence expression:
let transformed =
seq { for line in File.ReadLines(inFile) -> Regex.Replace(line, "\t",",") }
File.WriteAllLines(outFilePath, transformed)
I do not think there is any objective reason to prefer one of the versions. My personal stylistic preference is to use for and refactor to sequence expressions (if needed), but others will likely disagree.
A side note that if you want to write to the same file that you are reading from, you need to remember that Seq is doing lazy evaluation.
Using Array as opposed to Seq makes sure file is closed for reading when it is needed for writing.
This works:
let lines =
file |> File.ReadAllLines
|> Array.map(fun line -> ..modify line..)
File.WriteAllLines(file, lines)
This does not (causes file access file violation)
let lines =
file |> File.ReadLines
|> Seq.map(fun line -> ..modify line..)
File.WriteAllLines(file, lines)
(potential overlap with another discussion here, where intermediate variable helps with the same problem)

F# - weird behavior when pattern matching discriminated unions

I've been writing some F# now for about 6 months and I've come across some behavior that I can't explain. I have some boiled down code below. (value names have been changed to protect the innocent!)
I have a hierarchy defined using record types rec1 and rec2, and also a dicriminated union type with possible values CaseA and CaseB. I'm calling a function ('mynewfunc') that takes a du_rec option type. Internally this function defines a recursive function that processes the hierarchy .
I'm kicking off the processing by passing the None option value to represent the root of the hierarchy (In reality, this function is deserializing the hierarchy from a file).
When I run the code below I hit the "failwith "invalid parent"" line of code. I can not understand why this is, because the None value that is passed down should match the outer pattern matching's None case.
The code works if I delete either of the sets of comments. This is not a showstopper for me - I just feel a bit uncomfortable not knowing why this is happening (I thought I was understanding f#)
Thanks in advance for any replies
James
type rec2 =
{
name : string
child : rec1 option
}
and rec1 =
{
name : string ;
child : rec2 option
}
and du_rec =
| Case1 of rec1
| Case2 of rec2
let mynewfunc (arg:du_rec option) =
let rec funca (parent:du_rec option) =
match parent with
| Some(node) ->
match node with
| Case2(nd) ->
printfn "hello"
(* | Case1(nd) ->
printfn "bye bye" *)
| _ ->
failwith "invalid parent"
| None ->
// printfn "case3"
()
funcb( None )
and funcb (parent: du_rec option) =
printfn "this made no difference"
let node = funca(arg)
()
let rootAnnot = mynewfunc(None)
Based on the comments, this is just a bad experience in the debugger (where the highlighting suggests that the control flow is going places it is not); the code does what you expect.
(There are a number of places where the F# compiler could improve its sequence-points generated into the pdbs, to improve the debugging experience; I think we'll be looking at this in a future release.)

#indent "off" in F#

I just started learning F#, and tried a code from the wiki:
I prefer tabs to spaces, so I change the code a bit into this:
#indent "off"
open System
open System.Windows.Forms
let form = new Form(Visible=true, TopMost=true, Text="Welcome to F#")
let label =
let temp = new Label()
let x = 3 + (4 * 5)
temp.Text <- sprintf "x = %d" x
temp
form.Controls.Add(label)
[<STAThread>]
Application.Run(form)
The output is:
Microsoft (R) F# 2.0 Compiler build
4.0.30319.1 Copyright (c) Microsoft Corporation. All Rights Reserved.
fstest2.fs(1,1): warning FS0062: This
construct is for ML compatibility.
Conside r using a file with extension
'.ml' or '.mli' instead. You can
disable this warn ing by using
'--mlcompatibility' or '--nowarn:62'.
fstest2.fs(9,2): error FS0010:
Unexpected keyword 'let' or 'use' in
expression. Expected 'in' or other
token.
fstest2.fs(13,1): error FS0597:
Successive arguments should be
separated by spac es or tupled, and
arguments involving function or method
applications should be parenthesized
fstest2.fs(9,14): error FS0374:
Invalid expression on left of
assignment
fstest2.fs(16,1): error FS0010:
Unexpected identifier in definition
Guess the error is somewhere in the let label block, but couldn't figure it out.
If you use "#indent off", then you lose all the simpler whitespace-aware syntax, and have to go back to using e.g.
#indent "off"
open System
open System.Windows.Forms
let label =
let temp = new Label() in
let x = 3 + (4 * 5) in
temp.Text <- sprintf "x = %d" x;
temp;;
let form =
let f = new Form() in
f.Controls.Add(label);
f;;
[<STAThread>]
do Application.Run(form)
with semicolons and ins and all other kinds of syntactic noise everywhere. You'll probably be happier just having your editor convert tabs to spaces (and having a smart editor that can treat spaces as though they are tabs, e.g. so that backspace can back up one tab-stop).
This topic was already discussed in this StackOverflow question. As Brian explains, turning off the "lightweight" syntax means that you'll have to write in the OCaml-compatible syntax.
I believe that in most of the cases, the syntax based on indentation is more readable (and so it is worth switching from tabs to spaces). However, the syntax with additional noise (such as in and ;;) reveals more about the structure of the language, so it may be useful to play with it briefly while learning F#.
The following example shows all the additional things that you need to write:
let add a b c =
let ab = a + b in // 'in' keyword specifies where binding (value 'ab') is valid
printfn "%d" ab; // ';' is operator for sequencing expressions
c - ab;; // ';;' is end of a function declaration
For more discussions, see also this post.

Resources