F# Basic Syntax

When diving into F#, understanding the basic syntax is crucial for writing effective code. This article will guide you through the foundational components such as types, variables, and expressions. Both beginners and experienced programmers can benefit from mastering these essentials.

Types in F#

F# is a statically typed language, which means that types are checked at compile time. The F# type system can infer the types of most expressions, but knowing how to declare and use types explicitly is beneficial.

Basic Types

Here are fundamental types in F#:

  • Int: Represents integers. You can create an integer using an assignment like so:

    let number: int = 42
    
  • Float: Represents floating-point numbers. For example:

    let pi: float = 3.14159
    
  • String: Represents text and can be created using double quotes:

    let greeting: string = "Hello, F#"
    
  • Bool: Represents boolean values:

    let isFSharpAwesome: bool = true
    

Custom Types

You can also define your own types using type. Here’s how you can create a simple record type:

type Person = {
    Name: string
    Age: int
}

This defines a Person type with properties Name and Age. You can create an instance of this type as follows:

let john = { Name = "John Doe"; Age = 30 }

Variables in F#

In F#, variables are declared using the let keyword. Once defined, these variables cannot be changed, promoting immutability.

Declaring Variables

To declare a variable, do the following:

let age = 25

Here, F# infers that age is an int. If you want to be explicit with the type:

let age: int = 25

Mutable Variables

If you need a variable whose value can change, you can use the mutable keyword:

let mutable counter = 0
counter <- counter + 1  // Incrementing the mutable variable

Scope and Shadowing

Variables in F# are block-scoped. That means they are only accessible within the block they are defined. F# also allows shadowing, which means you can define a variable with the same name in a new scope:

let x = 10
if true then
    let x = 20  // This x shadows the outer x
    printfn "Inner x = %d" x
printfn "Outer x = %d" x

Expressions in F#

Expressions in F# are how you perform operations and compute values. Everything in F# is an expression, including function calls, calculations, and even declarations.

Arithmetic Expressions

You can perform mathematical operations on numbers using standard operators:

let sum = 5 + 3  // Addition
let difference = 5 - 2  // Subtraction
let product = 4 * 2  // Multiplication
let quotient = 8 / 4  // Division

Boolean Expressions

F# supports standard boolean operations:

let a = true
let b = false
let andResult = a && b  // Logical AND
let orResult = a || b  // Logical OR
let notResult = not a  // Logical NOT

Conditional Expressions

You can use if expressions to evaluate conditions:

let max a b =
    if a > b then a
    else b

Pattern Matching

One of the more powerful features in F# is pattern matching, which allows you to deconstruct types and control the flow based on specific patterns:

let describeNumber x =
    match x with
    | 0 -> "Zero"
    | 1 -> "One"
    | _ when x < 0 -> "Negative"
    | _ -> "Positive"

This function checks the value of x and provides a description based on its pattern.

Functions in F#

Functions are a core part of F# syntax. They are defined using the let keyword and can take parameters that are also typed.

Defining Functions

Here's a simple function definition:

let add x y = x + y

You can call the function like this:

let result = add 5 7  // result will be 12

Function Types

F# allows you to specify the types of the parameters and the return type as follows:

let add(x: int, y: int): int = x + y

Higher-Order Functions

F# supports higher-order functions, meaning you can pass functions as arguments or return them from other functions:

let applyFunc f x = f x

let square n = n * n

let result = applyFunc square 4  // result will be 16

Pipelining and Composition

F# provides a powerful way to chain operations using the pipeline operator (|>), which passes the result of one expression as input to the next:

let result =
    [1; 2; 3; 4; 5]
    |> List.map square
    |> List.sum  // Result will be 55

This clearly shows the flow of data through a series of transformations.

Conclusion

Understanding the basic syntax of F# is essential to leverage its powerful capabilities. With knowledge of types, variables, and expressions, you can start building robust applications. As you grow more familiar with F#, exploring its advanced features will become more intuitive.

Keep practicing these concepts, and soon you'll find yourself comfortable navigating the F# ecosystem!