From what I can gather, the DebuggerDisplayAttribute cannot be applied to individual levels of a discriminated union, only to the top-level class.
The corresponding documentation suggests that overriding the ToString() method is an alternative way.
Taking the following example:
type Target =
| Output of int
| Bot of int
override this.ToString () =
match this with
| Output idx -> $"output #{idx}"
| Bot idx -> $"bot #{idx}"
[<EntryPoint>]
let main _ =
let test = Bot 15
0
When breaking on the return from main and placing a watch on test, the VS2019 debugger is showing Bot 15 rather than bot #15.
The documentation also suggests that:
Whether the debugger evaluates this implicit ToString() call depends
on a user setting in the Tools / Options / Debugging dialog box.
I cannot figure out what user setting it is referring to.
Is this not available in VS2019 or am I just missing the point?
The main problem here is that the F# compiler silently emits a DebuggerDisplay attribute to override the default behavior described in the documentation you're looking at. So overriding ToString alone is not going to change what the debugger displays when debugging an F# program.
F# uses this attribute to implement its own plain text formatting. You can control this format by using StructuredFormatDisplay to call ToString instead:
[<StructuredFormatDisplay("{DisplayString}")>]
type Target =
| Output of int
| Bot of int
override this.ToString () =
match this with
| Output idx -> $"output #{idx}"
| Bot idx -> $"bot #{idx}"
member this.DisplayString = this.ToString()
If you do this, the Visual Studio debugger will display "bot #15", as you desire.
Another option is to explicitly use DebuggerDisplay yourself at the top level, as you mentioned:
[<System.Diagnostics.DebuggerDisplay("{ToString()}")>]
type Target =
| Output of int
| Bot of int
override this.ToString () =
match this with
| Output idx -> $"output #{idx}"
| Bot idx -> $"bot #{idx}"
FWIW, I think the direct answer to your question about the Tools / Options / Debugging setting is "Show raw structure of objects in variables windows". However, this setting isn't really relevant to the problem you're trying to solve.
Related
How do functional programmers test functions that return a unit?
In my case, I believe I need to unit test an interface to this function:
let logToFile (filePath:string) (formatf : 'data -> string) data =
use file = new System.IO.StreamWriter(filePath)
file.WriteLine(formatf data)
data
What is the recommended approach when I'm unit testing a function with I/O?
In OOP, I believe a Test Spy can be leveraged.
Does the Test Spy pattern translate to functional programming?
My client looks something like this:
[<Test>]
let ``log purchase``() =
[OneDollarBill] |> select Pepsi
|> logToFile "myFile.txt" (sprintf "%A")
|> should equal ??? // IDK
My domain is the following:
module Machine
type Deposit =
| Nickel
| Dime
| Quarter
| OneDollarBill
| FiveDollarBill
type Selection =
| Pepsi
| Coke
| Sprite
| MountainDew
type Attempt = {
Price:decimal
Need:decimal
}
type Transaction = {
Purchased:Selection
Price:decimal
Deposited:Deposit list
}
type RequestResult =
| Granted of Transaction
| Denied of Attempt
(* Functions *)
open System
let insert coin balance = coin::balance
let refund coins = coins
let priceOf = function
| Pepsi
| Coke
| Sprite
| MountainDew -> 1.00m
let valueOf = function
| Nickel -> 0.05m
| Dime -> 0.10m
| Quarter -> 0.25m
| OneDollarBill -> 1.00m
| FiveDollarBill -> 5.00m
let totalValue coins =
(0.00m, coins) ||> List.fold (fun acc coin -> acc + valueOf coin)
let logToFile (filePath:string) (formatf : 'data -> string) data =
let message = formatf data
use file = new System.IO.StreamWriter(filePath)
file.WriteLine(message)
data
let select item deposited =
if totalValue deposited >= priceOf item
then Granted { Purchased=item
Deposited=deposited
Price = priceOf item }
else Denied { Price=priceOf item;
Need=priceOf item - totalValue deposited }
Do not see this as an authoritative answer, because I'm not an expert on testing, but my answer to this question would be that, in a perfect world, you cannot and do not need to test unit-returning functions.
Ideally, you would structure your code so that it is composed from some IO to read data, transformations encoding all the logic and some IO to save the data:
read
|> someLogic
|> someMoreLogic
|> write
The idea is that all your important things are in someLogic and someMoreLogic and that read and write are completely trivial - they read file as string or sequence of lines. This is trivial enough that you do not need to test it (now, you could possibly test the actual file writing by reading the file back again, but that's when you want to test the file IO rather than any logic that you wrote).
This is where you would use a mock in OO, but since you have a nice functional structure, you would now write:
testData
|> someLogic
|> someMoreLogic
|> shouldEqual expectedResult
Now, in reality, the world is not always that nice and something like a spy operation ends up being useful - perhaps because you are interoperating with a world that is not purely functional.
Phil Trelford has a nice and very simple Recorder that lets you record calls to a function and check that it has been called with the expected inputs - and this is something I've found useful a number of times (and it is simple enough that you do not really need a framework).
Obviously, you could use a mock as you would in imperative code as long as the unit of code takes its dependencies as a parameter.
But, for another approach, I found this talk really interesting Mocks & stubs by Ken Scambler. As far as I recall the general argument was that you should avoid using mocks by keeping all functions as pure as possible, making them data-in-data-out. At the very edges of your program, you would have some very simple functions that perform the important side-effects. These are so simple that they don't even need testing.
The function you provided is simple enough to fall into that category. Testing it with a mock or similar would just involve ensuring that certain methods are called, not that the side-effect occurred. Such a test isn't meaningful and doesn't add any value over the code itself, while still adding a maintenance burden. It's better to test the side-effect part with an integration test or end-to-end test that actually looks at the file that was written.
Another good talk on the subject is Boundaries by Gary Bernhardt which Discusses the concept of Functional Core, Imperative Shell.
I'm new in F#.
How do I check whether a variable is an integer or another type.
Thanks.
One way is listed by #ildjarn in the comments:
let isInt x = box x :? int
An idiomatic way would be to use pattern matching. First, define a discriminated union which defines the possible options:
type Test =
| IsAnInteger of int
| IsADouble of double
| NotANumber of Object
then use a match statement to determine which option you got. Note that when you initially create the value you wish to use with a match statement, you need to put it into the discriminated union type.
let GetValue x =
match x with
| IsAnInteger(a) -> a
| IsADouble(b) -> (int)b
| NotAnInteger(_) -> 0
Since you're probably going to use your test to determine control flow, you might as well do it idiomatically. This can also prevent you from missing cases since match statements give you warnings if you don't handle all possible cases.
>GetValue (NotAnInteger("test"));;
val it : int = 0
>GetValue (IsADouble(3.3))
val it : int = 3
>GetValue (IsAnInteger(5))
val it : int = 5
Considering that you tagged this question "c#-to-f#" I'm assuming you're coming to F# from a C# background. Therefore I think you may be a bit confused by the type inference since you're probably used to explicitly typing variables.
You can explicitly declare the type of a value if you need to.
let x:int = 3
But it's usually easier and better to let the type inference do this work for you. You'll note that I said value--the declaration above is not a variable because you cannot do a destructive assignment to it. If you want a variable then do this:
let mutable x:int = 3
You can then assign a new value to x via this construct
x <- 5
But, as a rule, you'll want to avoid mutable values.
I'm a newbie to F# and I'm playing around with FParsec. I would use FParsec to generate an AST. I would like to use FsUnit to write some tests around the various parts of the parser to ensure correct operation.
I'm having a bit of trouble with the syntax (sorry, the exact code is at work, I can post a specific example later) so how exactly could one compare two discriminated unions (one the expected, the other the actual result)? Could someone provide a tiny code example using FsUnit (or NUnit), please?
An example discriminated union (very simple)
type AST =
| Variable of string
| Class of string
| Number of int
Since, as Brian pointed out, F# unions have structural equality, this is easy using whichever unit testing framework you are fond of.
FsUnit is an F# specific library built on top of NUnit. My personal favorite F# specific unit testing library is Unquote, ;), which is framework agnostic, working very well with NUnit, xUnit.net, MbUnit, ... or even within FSI. You may be interested in this comparison with FsUnit.
So, how would you do this with NUnit + Unquote? Here's a full working example:
module UnitTests
open NUnit.Framework
open Swensen.Unquote
type AST =
| Variable of string
| Class of string
| Number of int
let mockFParsec_parseVariable input = Variable(input)
[<Test>]
let ``test variable parse, passing example`` () =
test <# mockFParsec_parseVariable "x" = Variable("x") #>
[<Test>]
let ``test variable parse, failing example`` () =
test <# mockFParsec_parseVariable "y" = Variable("x") #>
Then running the tests using TestDriven.NET, the output is as follows:
------ Test started: Assembly: xxx.exe ------
Test 'UnitTests.test variable parse, failing example' failed:
UnitTests.mockFParsec_parseVariable "y" = Variable("x")
Variable "y" = Variable("x")
false
C:\xxx\UnitTests.fs(19,0): at UnitTests.test variable parse, failing example()
1 passed, 1 failed, 0 skipped, took 0.80 seconds (NUnit 2.5.10).
An example - if you want to check the type but not the contents
let matched x=
match x with
|Variable(_) -> true
| _ -> false
Note here that you need a different function for each element of the discriminated union
If you want to compare equality, you can just do it in the standard way, like
Assert.AreEqual(Variable("hello"),result)
or
if result = Variable("hello") then stuff()
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)))
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.)