Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

What does F#'s `box` keyword do and where is it documented?

+3
−0

The Null Values article in the F# Language Reference show an example that uses it, but it does not explain what it does exactly.

You can use the following code to check if an arbitrary value is null.

match box value with
| null -> printf "The value is null."
| _ -> printf "The value is not null."

I went through the entire PDF version of the language reference, but there is not trace of it ever being introduced.

History
Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

1 answer

+3
−0

box and unbox are operators documented in the F# Core API Reference; it tersely states that they box / unbox (respectively) a strongly typed value.

  • box a returns value a "wrapped" in a .NET System.Object instance

    "wrapped" here simply means that a is upcast to System.Object:

    type Lofa = | A | B
    
    match      A  with         | :? Lofa -> A //=> error FS0016
    match (box A) with         | :? Lofa -> A //ok
    match (A :> obj)           | :? Lofa -> A //ok
    match (A :> System.Object) | :? Lofa -> A //ok
    
  • unbox<a_type> a will try to unwrap value a and cast it into an a_type or throw an exception otherwise

For completeness' sake, there is also a tryUnbox operator, that can be called the same way as unbox, but it returns the boxed value wrapped in an Option.

Example use cases

1. Type detection during runtime

The F# for Fun and Profit article Built-in .NET types1 has an entire section dedicated to box and unbox which ends with the following example:

[1]: That is, types of the Common Language Infrastructure (CLI).

Let’s say that you want to have a function that matches based on the type of the parameter, using the :? operator:

let detectType v =
    match v with
        | :? int -> printfn "this is an int"
        | _ -> printfn "something else"

Unfortunately, this code will fail to compile, with the following error:

// error  FS0008: This  runtime coercion  or type  test
// from type  'a to int involves  an indeterminate type
// based on  information prior  to this  program point.
// Runtime type  tests are  not allowed on  some types.
// Further type annotations are needed.

The message tells you the problem: runtime type tests are not allowed on some types.

The answer is to “box” the value which forces it into a reference type, and then you can type check it:

let detectTypeBoxed v =
    match box v with      // used "box v"
        | :? int -> printfn "this is an int"
        | _ -> printfn "something else"

//test
detectTypeBoxed 1
detectTypeBoxed 3.14

2. Interoperability with non-F# .NET projects

The Functional Adam post What is box in F#? nicely complements the example in the question:

The Problem - The variable was in Int, it was required, and if it was not provided, our application was supposed to return an error code. When the parameter was not provided, WebAPI would set the required parameter to null even though Int cannot be null. This was very confusing, and, to make matters worse, we were not able to make the required parameter a Nullable<Int> with WebAPI.

The Solution - Box is the solution! From our searching, by boxing the int we could check if it is null even though it's not nullable (confusing). But what does the box function do? According to [the docs], the box function in F# "boxes a strongly typed value". Ok... Thanks documentation.

That's not all very helpful, but with further digging in [the Boxing and Unboxing article of the C# Programming Guide], the answer is

Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. When the common language runtime (CLR) boxes a value type, it wraps the value inside a System.Object instance and stores it on the managed heap. Unboxing extracts the value type from the object. Boxing is implicit; unboxing is explicit. The concept of boxing and unboxing underlies the C# unified view of the type system in which a value of any type can be treated as an object.

So, boxing a value wraps the value type inside a System.Object and therefore we can check if the object is null. Then we have to unbox it back to an Int after the null check.

History
Why does this post require moderator attention?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »