Hiring guide for F* Engineers

F* Developer Hiring Guide

The F* (F Star) computer programming language is a sophisticated, statically-typed functional programming language developed by Microsoft Research. It was designed for program verification, enabling developers to write annotations expressing properties they want their programs to have. The F* type-checker aims to prove these properties via an automated theorem prover. This language is used in several Microsoft projects, including Project Everest, which aims to build a verified HTTPS stack. Its development and application are documented in numerous research papers published by Microsoft Research.

Ask the right questions secure the right F* talent among an increasingly shrinking pool of talent.

First 20 minutes

General F* app knowledge and experience

The first 20 minutes of the interview should seek to understand the candidate's general background in F* application development, including their experience with various programming languages, databases, and their approach to designing scalable and maintainable systems.

How would you explain the purpose of F*?
F* is a functional programming language aimed at program verification. It puts forth a mechanism to define the specification of a program and verify the program against the specification.
What are the benefits of using F* over other languages?
F* provides strong type-checking, effect system, and a powerful system for defining and proving properties about programs.
Describe the difference between F* and other functional languages like Haskell or OCaml.
The main difference is that F* has a built-in mechanism for program verification. It allows programmers to write specifications and prove them as part of the program.
How would you handle side-effects in F*?
F* has a mechanism known as the 'effect system'. This allows programmers to mark functions with their side-effects, which are then checked during the verification process.
What are the basic data types in F*?
F* includes basic data types like integers, booleans, strings, and more complex ones like lists, options, and references.
The hiring guide has been successfully sent to your email address.
Oops! Something went wrong while submitting the form.

What you’re looking for early on

Does the candidate demonstrate a strong understanding of F* programming language?
Has the candidate shown problem-solving abilities?
Is the candidate able to articulate their thoughts and ideas clearly?
Does the candidate have experience with relevant tools and technologies?

Next 20 minutes

Specific F* development questions

The next 20 minutes of the interview should focus on the candidate's expertise with specific backend frameworks, their understanding of RESTful APIs, and their experience in handling data storage and retrieval efficiently.

Describe the difference between dependent types in F* and traditional type systems.
Dependent types in F* allow types to depend on values, which provides a way to express more precise types and invariants. Traditional type systems usually don't have this feature.
How would you use F*'s dependent types to improve a program's correctness?
Dependent types can be used to express precise properties about a program. For example, you can define a type of sorted lists and then write functions that only operate on sorted lists.
What is the role of the Z3 solver in F*?
F* uses the Z3 solver to automatically prove properties about programs. It translates the verification conditions into logical formulas that Z3 can solve.
How would you handle a situation where Z3 cannot prove a property?
In such cases, you can provide additional hints or lemmas to help Z3. If that's not possible, you can also use a manual proof mode to guide the proof.
What are the limitations of F*?
F* is not as mature or widely used as other languages, so it may lack libraries and tooling. Also, writing specifications and proofs can be time-consuming.
The hiring guide has been successfully sent to your email address.
Oops! Something went wrong while submitting the form.

The ideal back-end app developer

What you’re looking to see on the F* engineer at this point.

At this point, a skilled F* engineer should demonstrate strong problem-solving abilities, proficiency in F* programming language, and knowledge of software development methodologies. Red flags include lack of hands-on experience, inability to articulate complex concepts, or unfamiliarity with standard coding practices.

Digging deeper

Code questions

These will help you see the candidate's real-world development capabilities with F*.

What does the following F# code do?
let square x = x * x
This code defines a function named 'square' that takes an argument 'x' and returns the square of 'x'.
What will be the output of the following F# code?
let x = 5
let y = 3
printfn "%d" (x % y)
The output will be '2'. The code calculates the remainder of the division of 'x' by 'y'.
What does the following F# code do?
let list1 = [1;2;3;4;5]
let list2 = List.map (fun x -> x * 2) list1
This code creates a new list 'list2' by applying a function that multiplies each element of 'list1' by 2.
What does the following F# code do?
let mutable counter = 0
[]
do while counter < 5 do
    counter <- counter + 1
This code creates a mutable variable 'counter' and increments it in a loop until it reaches 5. The [] attribute indicates that the COM threading model for an application is single-threaded apartment.

Wrap-up questions

Final candidate for F* Developer role questions

The final few questions should evaluate the candidate's teamwork, communication, and problem-solving skills. Additionally, assess their knowledge of microservices architecture, serverless computing, and how they handle F* application deployments. Inquire about their experience in handling system failures and their approach to debugging and troubleshooting.

How would you use F* to verify a complex algorithm?
First, I would define the specification of the algorithm using F*'s type system. Then, I would write the algorithm and use F*'s verification mechanism to prove that it meets the specification.
Describe the difference between total and partial functions in F*.
Total functions in F* are guaranteed to terminate and not throw exceptions, while partial functions may not terminate or throw exceptions. F* checks totality by default.
How would you handle non-termination in F*?
F* has a 'div' effect for non-terminating computations. You can use this effect to explicitly mark non-terminating functions.

F* application related

Product Perfect's F* development capabilities

Beyond hiring for your F* engineering team, you may be in the market for additional help. Product Perfect provides seasoned expertise in F* projects, and can engage in multiple capacities.