This Note contains:
- Introduction of functional Programming
- F# ide setup
- F# Syntax
- F# types
- What is functional programming?
- F# IDE Setup
- Mathematical function example in F#
- Syntax
- Function Type
- Function application
- Function interactive
- The power of functions
- Types in F#
What is functional programming?
Functional programming is a programming paradigm characterized by the use of mathematical functions and the avoidance of side effect
- fundamental approach to structuring programs
- via application and composition of functions
What constitutes a function?
A function include:
- The input
- The relationship
- The output
A function is anything which accepts exactly one input value and, when this is supplied, evaluates an expression
to generate exactly one output value.
Properties of function
One input - one output
There is always exactly one input and one output
Immutability
- Value once created, can never be altered
- The input and output values are immutable
- Work with copies of data instead
Depending only on input
- Function output is solely determined by its input parameter
- Can your function possibly return a different result when given the same input?
- Mutable global variables
- User input
- Random numbers generator
Side Effect
Side effect is an unwanted or unexpected result or condition that comes along with the desired effects of something.
There is also “functional” side effect
- Observable interaction of a function with anything outside of it
- Anything more than computation of a result based on input parameters
Example
- Altering a variable outside of the function
- Writing data to a file
- Displaying something on the screen
- Sending data over the network
A function should have no side effect. It doesn’t change the input or output.
Pure function
Two properties make a function “pure”
- Its output depends only on its input
- It has no side-effects
Referential Transparency
Calling a function with the same input results in the same output
- One can replace a function call with its result, without affecting the behavior of the program
- It makes your code easy to read and understand
F# IDE Setup
Visual Studio Code
- Download Visual Studio Code: https://code.visualstudio.com/downloadLinks to an external site..
- Open VS Code by launching the downloaded file and go to the “Extensions“ tab (on the left). Install plugins: Ionide F#, C# (Microsoft’s plugin) and fsharp-language-server for Visual Studio Code.
- Download and install the latest version of SDK from https://dotnet.microsoft.com/en-us/download/dotnet/6.0Links to an external site.
- Open a command line.
- Check the home directory of .NET SDK on your machine (most likely on MacOS: /usr/local/share/dotnet/dotnet) by typing the following command:
find / -name dotnet
- Add .NET to the PATH (update the last part to reflect your local settings looked up in step 5):
export PATH=$PATH:/usr/local/share/dotnet/dotnet
- Restart your machine
- Navigate to a parent directory of choice for your F# project.
- Create a new project with the .NET CLI by executing the command:
dotnet new console -lang "F#" -o NameOfTheProject
- Open the parent folder of the project in VS Code and you’re ready to code!
- Follow this tutorialLinks to an external site. to put in place DEBUG support in VS Code.
JetBrain Rider
JetBrains Rider is a cross-platform .NET IDE built using IntelliJ and ReSharper technology. It offers support for .NET and .NET Core applications on all platforms.
- Get a students license hereLinks to an external site. before installing the tool.
- Download the installerLinks to an external site. and follow the installation wizard. You can refer to this YT tutorialLinks to an external site. (optional).
- Check the F# support plugin is enabled:
- 3a. Press Ctrl + Alt + S to open the IDE settings and then select Plugins. Alternatively, click on “Jetbrains Rider”/Preferences in the Mac menu bar.
- 3b. Open the “Installed” tab, find the “F# Support” plugin, and select the checkbox next to the plugin name.
- Create a F# Console project:
- 4a. In the side panel on startup select Projects -> New Solution
- 4b. Search for F#
- 4c. Click on console application
- Check that F# interactive is activated as per this documentLinks to an external site..
- Using the F# interactive:
- 6a. Select the code to evaluate and click “Alt + Enter”
- 6b. Assign a shortcut of your choice
- Debugging in JetBrains Rider: refer to this documentLinks to an external site..
Mathematical function example in F#
increment a number by 1 : Add1(x) = x + 1
1 | let add1 x = x + 1 |
let
keyword defines a function and binds an identifier with a function
Function binding includes function name and function parameter
Function body is an expression that generates a return value
Syntax
- Parameters are separated by space
- The output of the function is the last expression in its definition
- Use indents for multi-line functions
Your first F# function
BMI calculator
$BMI = 703 * weight / height^{2}$
1 | let bmi weight height = |
F# type inference
F# infers the parameter and return types when they’re not explicitly specified
- When argument type is not specified, function body is used to infer it.
- When return type is not specified, final body expression is used to infer it
Function signature
F# use type syntax for function signatures.
It denotes the types used and produced by a function.
1 | // example of function signature |
Function Type
All functions are values therefore have a type.
Function type is prescribed by its input and output types.
1 | // function signature |
function with generic types:
- if a function works with any type, the compiler automatically infers a generic type
- Notation: letter preceded by a tick: `a
1
2let areEqual x y =
(x = y)
Equality test in F# is
=
operator
Function application
Function definition and application are separate.
Function is applied by providing its input, separated by a space
1 | let bmi weight height = |
Function interactive
To run F# code in the console:
- Select the code you want to execute
- Click on “Option” + “Enter” in Mac OS
- “Alt” + “Enter” in Window instead
The power of functions
Functions can be bound to identifiers.
1 | let plus3 x = x + 3 |
Functions can be stored in data structures.
1 | let listofFunctions = [plus; times2] |
Functions can be passed down as an argument to other functions.
Functions can be a return value from a function call.
Types in F#
A type is a description of a set of values and a set of allowed operations on those values
A value is a member of a type.
A identifier is a name supply for a type or a function in program.
Basic type
Data type built into F#
- byte, int, float, double
- string, char
- bool
- unit
- indicates the absence of an actual value
- one possible value: ( )
- strong sign of possible side effects
Composition type
Gather types into large structures
composition with And or Or operation.
Tuple
A grouping of unnamed but ordered values, possibly of different types.
1 | (1, 2) |
Value separated by coma, encompassed by parentheses.
Tuples can contain values of multiple types.
Types: The type of a tuple is multiplication of type of each of its components
1 | let personalInfo = ("Ted", "Lester", 32, 6.4, 94101) |
- The order of the multiplication is important!
Accessing tuple element via library function
- fst : return the first element of a tuple
- snd: return the second element of a tuple
fst and snd functions require that the tuple be a pair (2-element tuple)
pros & cons
Pros:
- Available without definition
- Can contain values of different types
- lightweight structure
Cons:
Difficult to figure out meaning of values
when dealing with multiple values, order might be confused
Comparison:
If all the values in a tuple are comparable, then the tuple is comparable to another tuple of the same type.
1 | let myName = ("Rafal", "Wlodarski") |
Tuples can be compared using equality operation.
1 | myName = cityState // false |
Records
A grouping of named values
Definition:
1 | type GeoCoord = { Lat: float; Long: float } |
Construction:
1 | let point3D1 = {Point3D.X = 0.1; |
Copy and update record expression:
1 | let point3D2 = {point3D1 with Y = 0.4} |
Accessing record elements via “dot” notation.
1 | let geoCoord1 = { Lat = 1.1; Long = 2.2 } |
Pros & Cons:
Pros:
Allow to organize values into a type
Named field helps understand what a program is doing
Provide Class-like feature
Cons:
Immutable
Has to define before using
Comparison:
Like tuples, records have structural equality semantics
1 | let geoCoord1 = { Lat = 1.1; Long = 2.2 } |
Two records are equal if they have the same type and the values in each slot are equal.
Discriminated Union
Data structure representing a set of choices.
- Supports values from a number of named cases
- Each alternative is called a case
1 | type AppleVariety = |
- Each case must be tagged with a label, also called identifier or tag
- Each case identifier must start with am UPPERCASE LETTER
- Case values are optional
- Each case can have different values and types
1 | type FruitSnack = |
- *”of type”* syntax allows to indicate the data type of a case
Construction
Use a constructor that refers to one of the possible union cases.
1 | type AppleVariety = |
1 | type Shape = |
During initialization use the named fields or rely on ordering of fields
1 | let rectangle2 = Rectangle (width = 1.5, length = 2.2) |
Simple Type:
A simple type discriminated union is a Discriminated Union with one case only.
1 | type ProductCode = |
Used as a wrapper data type for primitive values
1 | let a = ProductCode "ABC123" |
Comparison:
Two unions are equal if they have the same type and the same case and the values for that case is equal.
1 | type Contact = |
Option
A Discriminated Union with two cases: value of some type and None
1 | type MiddleName = |
Used when anticipated that there might or might not be a value.
Exercise: Match usage scenario with data type
F# specific types
Common .NET types
- User-defined value types (enum and struct)
- Classes and interfaces
- Arrays
Designed for pure functional programming
- The unit type
- Tuples
- Records
- Discriminated Unions
- Option types
- Lists
F# functional types - Advantage
- They are immutable
- They cannot be null
- They have built-in structural equality and comparison
- They have built-in pretty printing
- 本文作者: Depasinre
- 本文链接: https:/Depasinre.github.io/2024/01/23/18656-week1/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!