{"id":15060962,"url":"https://github.com/adelarsq/fsharp-cheatsheet","last_synced_at":"2025-04-10T06:12:04.315Z","repository":{"id":40573916,"uuid":"417324945","full_name":"adelarsq/fsharp-cheatsheet","owner":"adelarsq","description":"An updated cheat sheet for F# 🔷🦔💙💛🤍💚","archived":false,"fork":false,"pushed_at":"2023-01-02T21:05:28.000Z","size":540,"stargazers_count":221,"open_issues_count":0,"forks_count":9,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-03-24T07:22:00.187Z","etag":null,"topics":["blacklivesmatter","cheatsheet","dotnet","fsharp","fsharp-cheatsheet","nowar","reference"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adelarsq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-15T00:45:49.000Z","updated_at":"2025-01-21T22:22:14.000Z","dependencies_parsed_at":"2023-02-01T04:17:23.490Z","dependency_job_id":null,"html_url":"https://github.com/adelarsq/fsharp-cheatsheet","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adelarsq%2Ffsharp-cheatsheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adelarsq%2Ffsharp-cheatsheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adelarsq%2Ffsharp-cheatsheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adelarsq%2Ffsharp-cheatsheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adelarsq","download_url":"https://codeload.github.com/adelarsq/fsharp-cheatsheet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248166925,"owners_count":21058481,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blacklivesmatter","cheatsheet","dotnet","fsharp","fsharp-cheatsheet","nowar","reference"],"created_at":"2024-09-24T23:07:24.586Z","updated_at":"2025-04-10T06:12:04.291Z","avatar_url":"https://github.com/adelarsq.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# F# Cheatsheet 🔷\n\nAn updated cheatsheet for [F#](https://fsharp.org/).\n\nThis cheatsheet glances over some of the common syntax of F#.\n\nContents\n--------\n- [Comments](#Comments)  \n- [Strings](#Strings)  \n- [Types and Literals](#TypesAndLiterals)  \n- [Printing Things](#PrintingThings)  \n- [Loops](#Loops)  \n- [Values](#Values)  \n- [Functions](#Functions)  \n- [Pattern Matching](#PatternMatching)  \n- [Collections](#Collections)  \n- [Records](#Records)  \n- [Discriminated Unions](#DiscriminatedUnions)  \n- [Exceptions](#Exceptions)  \n- [Classes and Inheritance](#ClassesAndInheritance)  \n- [Interfaces and Object Expressions](#InterfacesAndObjectExpressions)  \n- [Casting and Conversions](#CastingAndConversions)  \n- [Active Patterns](#ActivePatterns)  \n- [Compiler Directives](#CompilerDirectives)  \n- [Acknowledgments](#Acknowledgments)  \n\n-------------------\n\n\u003ca name=\"Comments\"\u003e\u003c/a\u003eComments\n--------\n\nLine comments start from `//` and continue until the end of the line. Block comments are placed between `(*` and `*)`.\n\n```fsharp\n// And this is line comment\n(* This is block comment *)\n```\n\n[XML doc comments](https://docs.microsoft.com/dotnet/fsharp/language-reference/xml-documentation) come after `///` allowing us to use XML tags to generate documentation.    \n    \n```fsharp\n/// The `let` keyword defines an (immutable) value\nlet result = 1 + 1 = 2\n```\n\n\u003ca name=\"Strings\"\u003e\u003c/a\u003eStrings\n-------\n\nThe F# `string` type is an alias for `System.String` type. See [Strings](https://docs.microsoft.com/dotnet/fsharp/language-reference/strings).\n\n```fsharp\n/// Create a string using string concatenation\nlet hello = \"Hello\" + \" World\"\n```\n\nUse *verbatim strings* preceded by `@` symbol to avoid escaping control characters (except escaping `\"` by `\"\"`).\n\n```fsharp\nlet verbatimXml = @\"\u003cbook title=\"\"Paradise Lost\"\"\u003e\"\n```\n\nWe don't even have to escape `\"` with *triple-quoted strings*.\n\n```fsharp\nlet tripleXml = \"\"\"\u003cbook title=\"Paradise Lost\"\u003e\"\"\"\n```\n\n*Backslash strings* indent string contents by stripping leading spaces.\n\n```fsharp\nlet poem = \n    \"The lesser world was daubed\\n\\\n     By a colorist of modest skill\\n\\\n     A master limned you in the finest inks\\n\\\n     And with a fresh-cut quill.\"\n```\n\n[Interpolated strings](https://docs.microsoft.com/dotnet/fsharp/language-reference/interpolated-strings) let you write code in \"holes\" inside of a string literal:\n\n```fsharp\nlet name = \"Phillip\"\nlet age = 30\nprintfn $\"Name: {name}, Age: {age}\"\n\nlet str = $\"A pair of braces: {{}}\"\nprintfn $\"Name: %s{name}, Age: %d{age}\" // typed\n```\n\n\u003ca name=\"TypesAndLiterals\"\u003e\u003c/a\u003eTypes and Literals\n------------------------\n\nMost numeric types have associated suffixes, e.g., `uy` for unsigned 8-bit integers and `L` for signed 64-bit integer.\n\n```fsharp\nlet b, i, l, ul = 86uy, 86, 86L, 86UL\n\n// val ul: uint64 = 86UL\n// val l: int64 = 86L\n// val i: int = 86\n// val b: byte = 86uy\n```\n\nOther common examples are `F` or `f` for 32-bit floating-point numbers, `M` or `m` for decimals, and `I` for big integers.\n\n```fsharp\nlet s, f, d, bi = 4.14F, 4.14, 0.7833M, 9999I\n\n// val bi: System.Numerics.BigInteger = 9999\n// val d: decimal = 0.7833M\n// val f: float = 4.14\n// val s: float32 = 4.14f\n```\n\nSee [Literals](https://docs.microsoft.com/dotnet/fsharp/language-reference/literals) for complete reference.\n\n`and` keyword is used for definining mutually recursive types and functions:\n\n```fsharp\ntype A = \n  | Aaa of int \n  | Aaaa of C\nand C = \n  { Bbb : B }\nand B() = \n  member x.Bbb = Aaa 10\n```\n\nFloating point and signed integer values in F# can have associated [units of measure](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/units-of-measure), which are typically used to indicate length, volume, mass, and so on:\n\n```fsharp\n[\u003cMeasure\u003e] type kg\nlet m1 = 10.0\u003ckg\u003e\nlet m2 = m1 * 2.0 // type inference for result \nlet add30kg m =   // type inference for input and output\n    m + 30.0\u003ckg\u003e\nadd30 2.0\u003ckg\u003e     // val it: float\u003ckg\u003e = 32.0\n```\n\n\u003ca name=\"PrintingThings\"\u003e\u003c/a\u003ePrinting Things\n------------------------\n\nPrint things to console with `printfn`:\n\n```fsharp\nprintfn \"Hello, World\"\n\nprintfn $\"The time is {System.DateTime.Now}\"\n```\n\nYou can also use `Console.WriteLine`:\n```fsharp\nopen System\n\nConsole.WriteLine $\"The time is {System.DateTime.Now}\"\n```\n\nConstrain types with `%d`, `%s`, and print structured values with `%A`:\n\n```fsharp\nlet data = [1..10]\n\nprintfn $\"The numbers %d{1} to %d{10} are %A{data}\"\n```\n\nOmit holes and apply arguments:\n\n```fsharp\nprintfn \"The numbers %d to %d are %A\" 1 10 data\n```\n\nSee [Plaintext Formatting](https://docs.microsoft.com/dotnet/fsharp/language-reference/plaintext-formatting)\n\n\u003ca name=\"Loops\"\u003e\u003c/a\u003eLoops\n---------\n\n### for...in\n\n[For loops](https://docs.microsoft.com/dotnet/fsharp/language-reference/loops-for-in-expression):\n\n```fsharp\nlet list1 = [1; 5; 100; 450; 788]\n\nfor i in list1 do\n    printf \"%d\" i           // 1 5 100 450 788\n\nlet seq1 = seq { for i in 1 .. 10 -\u003e (i, i * i) }\n\nfor (a, asqr) in seq1 do\n    // 1 squared is 1\n    // ...\n    // 10 squared is 100\n    printfn \"%d squared is %d\" a asqr\n\nfor i in 1 .. 10 do\n    printf \"%d \" i          // 1 2 3 4 5 6 7 8 9 10\n\n// for i in 10 .. -1 .. 1 do\nfor i = 10 downto 1 do\n    printf \"%i \" i          // 10 9 8 7 6 5 4 3 2 1\n\nfor i in 1 .. 2 .. 10 do\n    printf \"%d \" i             // 1 3 5 7 9\n\nfor c in 'a' .. 'z' do\n    printf \"%c \" c          // a b c ... z\n\n// Using of a wildcard character (_)\n// when the element is not needed in the loop.\nlet mutable count = 0\n\nfor _ in list1 do\n    count \u003c- count + 1\n```\n\n### while...do\n\n[While loops](https://docs.microsoft.com/dotnet/fsharp/language-reference/loops-while-do-expression):\n\n```fsharp\nlet mutable mutVal = 0\nwhile mutVal \u003c 10 do        // while (not) test-expression do\n    mutVal \u003c- mutVal + 1\n```\n\n\u003ca name=\"Values\"\u003e\u003c/a\u003eValues\n------------------\n\nValues have different names based on length, called unit, single value and tuples.\n\n```fsharp\n// unit (no value)\nlet nothing = ()\n\n// single value\nlet single = 1 // same as `let single = (1)`\n```\n\nFunctions that return void in C# will return the unit type in F#.\n\nA *tuple* is a grouping of unnamed but ordered values, with lenght equal or bigger than 2 and possibly of different types:\n\n```fsharp\n// 2-tuples\nlet x = (1, \"Hello\")\n\n// 3-tuples\nlet y = (\"one\", \"two\", \"three\") \n\n// Tuple deconstruction\nlet (a', b') = x\nlet (c', d', e') = y\n\n// The first and second elements of a tuple can be obtained using `fst`, `snd`, or pattern matching:\nlet c' = fst (1, 2)\nlet d' = snd (1, 2)\n  \nlet print' tuple =\n    match tuple with\n    | (a, b) -\u003e printfn \"Pair %A %A\" a b\n```\n\n\u003ca name=\"Functions\"\u003e\u003c/a\u003eFunctions\n---------\n\nThe [`let`](https://docs.microsoft.com/dotnet/fsharp/language-reference/functions/let-bindings) keyword also defines named functions.\n\n```fsharp\nlet pi () = 3.14159 // function with no arguments. () is called unit type\npi ()               // it's necessary to use () to call the function\n\nlet negate x = x * -1 \nlet square x = x * x \nlet print x = printfn $\"The number is: %d{x}\"\n\nlet squareNegateThenPrint x = \n    print (negate (square x)) \n```\n\nDouble-backtick identifiers are handy to improve readability especially in unit testing:\n\n```fsharp\nlet ``square, negate, then print`` x = \n    print (negate (square x)) \n```\n\n### Pipe operator\n\nThe pipe operator `|\u003e` is used to chain functions and arguments together:\n\n```fsharp\nlet squareNegateThenPrint x = \n    x |\u003e square |\u003e negate |\u003e print\n```\n\nThis operator is essential in assisting the F# type checker by providing type information before use:\n\n```fsharp\nlet sumOfLengths (xs : string []) = \n    xs \n    |\u003e Array.map (fun s -\u003e s.Length)\n    |\u003e Array.sum\n```\n\n### Composition operator\n\nThe composition operator `\u003e\u003e` is used to compose functions:\n\n```fsharp\nlet squareNegateThenPrint = \n    square \u003e\u003e negate \u003e\u003e print\n```\n  \n\u003ca name=\"PatternMatching\"\u003e\u003c/a\u003ePattern Matching\n----------------\n\nPattern matching is primarily through `match` keyword;\n\n```fsharp\nlet rec fib n =\n    match n with\n    | 0 -\u003e 0\n    | 1 -\u003e 1\n    | _ -\u003e fib (n - 1) + fib (n - 2)\n```\n\nUse `when` to create filters or guards on patterns:\n\n```fsharp\nlet sign x = \n    match x with\n    | 0 -\u003e 0\n    | x when x \u003c 0 -\u003e -1\n    | x -\u003e 1\n```\n\nPattern matching can be done directly on arguments:\n\n```fsharp\nlet fst (x, _) = x\n```\n\nor implicitly via `function` keyword:\n\n```fsharp\n/// Similar to `fib`; using `function` for pattern matching\nlet rec fib2 = function\n    | 0 -\u003e 0\n    | 1 -\u003e 1\n    | n -\u003e fib2 (n - 1) + fib2 (n - 2)\n```\n\nSee [Pattern Matching](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching).\n\n\u003ca name=\"Collections\"\u003e\u003c/a\u003eCollections\n-----------\n\n### Lists\n\n[*Lists*](https://docs.microsoft.com/dotnet/fsharp/language-reference/lists) are immutable collection of elements of the same type.\n\n```fsharp\n// Lists use square brackets and `;` delimiter\nlet list1 = [\"a\"; \"b\"]\n\n// :: is prepending\nlet list2 = \"c\" :: list1\n\n// @ is concat    \nlet list3 = list1 @ list2   \n\n// Recursion on list using (::) operator\nlet rec sum list = \n    match list with\n    | [] -\u003e 0\n    | x :: xs -\u003e x + sum xs\n```\n\n### Arrays\n\n[*Arrays*](https://docs.microsoft.com/dotnet/fsharp/language-reference/arrays) are fixed-size, zero-based, mutable collections of consecutive data elements.\n\n```fsharp\n// Arrays use square brackets with bar\nlet array1 = [| \"a\"; \"b\" |]\n\n// Indexed access using dot\nlet first1 = array1.[0]   \nlet first2 = array1[0]    // F# 6\n```\n      \n### Sequences == IEnumerable\n\n[*Sequences*](https://docs.microsoft.com/dotnet/fsharp/language-reference/sequences) are logical series of elements of the same type. Individual sequence elements are computed only as required, so a sequence can provide better performance than a list in situations in which not all the elements are used.\n\n```fsharp\n// Sequences can use yield and contain subsequences\nseq {\n    // \"yield\" adds one element\n    yield 1\n    yield 2\n\n    // \"yield!\" adds a whole subsequence\n    yield! [5..10]\n}\n```\n\nThe `yield` can normally be omitted:\n\n```fsharp\n// Sequences can use yield and contain subsequences\nseq {\n    1\n    2\n    yield! [5..10]\n}\n```\n\n### Mutable Dictionaries (from BCL)\n\nCreate a dictionary, add two entries, remove an entry, lookup an entry\n\n```fsharp\nopen System.Collections.Generic\n\nlet inventory = Dictionary\u003cstring, float\u003e()\n\ninventory.Add(\"Apples\", 0.33)\ninventory.Add(\"Oranges\", 0.5)\n\ninventory.Remove \"Oranges\"\n\n// Read the value. If not exists - throw exception.\nlet bananas1 = inventory.[\"Apples\"]\nlet bananas2 = inventory[\"Apples\"]   // F# 6\n```\n\nAdditional F# syntax:\n\n```fsharp\n// Generic type inference with Dictionary\nlet inventory = Dictionary\u003c_,_\u003e()   // or let inventory = Dictionary()\n\ninventory.Add(\"Apples\", 0.33)\n```\n\n### dict == IDictionary in BCL\n\n*dict* creates immutable dictionaries. You can’t add and remove items to it.\n\n```fsharp\nopen System.Collections.Generic\n\nlet inventory : IDictionary\u003cstring, float\u003e =\n    [\"Apples\", 0.33; \"Oranges\", 0.23; \"Bananas\", 0.45]\n    |\u003e dict\n\nlet bananas = inventory.[\"Bananas\"]     // 0.45\nlet bananas2 = inventory[\"Bananas\"]     // 0.45, F# 6\n\ninventory.Add(\"Pineapples\", 0.85)       // System.NotSupportedException\ninventory.Remove(\"Bananas\")             // System.NotSupportedException\n```\n\nQuickly creating full dictionaries:\n\n```\n[ \"Apples\", 10; \"Bananas\", 20; \"Grapes\", 15 ] |\u003e dict |\u003e Dictionary\n```\n\n### Map\n\n*Map* is an immutable key/value lookup. Allows safely add or remove items.\n\n```fsharp\nlet inventory =\n    Map [\"Apples\", 0.33; \"Oranges\", 0.23; \"Bananas\", 0.45]\n\nlet apples = inventory.[\"Apples\"]\nlet apples = inventory[\"Apples\"] // F# 6\nlet pineapples = inventory.[\"Pineapples\"]   // KeyNotFoundException\nlet pineapples = inventory[\"Pineapples\"]    // KeyNotFoundException on F# 6 too\n\nlet newInventory =              // Creates new Map\n    inventory\n    |\u003e Map.add \"Pineapples\" 0.87\n    |\u003e Map.remove \"Apples\"\n```\n\nSafely access a key in a *Map* by using *TryFind*. It returns a wrapped option:\n\n```fsharp\nlet inventory =\n    Map [\"Apples\", 0.33; \"Oranges\", 0.23; \"Bananas\", 0.45]\n\ninventory.TryFind \"Apples\"      // option = Some 0.33\ninventory.TryFind \"Unknown\"     // option = None\n```\n\nUseful Map functions include `map`, `filter`, `partition`:\n\n```fsharp\nlet cheapFruit, expensiveFruit =\n    inventory\n    |\u003e Map.partition(fun fruit cost -\u003e cost \u003c 0.3)\n```\n\n### Dictionaries, dict, or Map?\n\n* Use *Map* as your default lookup type:\n    * It’s immutable\n    * Has good support for F# tuples and pipelining.\n\n* Use the *dict* function\n    * Quickly generate an *IDictionary* to interop with BCL code.\n    * To create a full Dictionary.\n\n* Use *Dictionary*:\n    * If need a mutable dictionary.\n    * Need specific performance requirements. (Example: tight loop performing\n      thousands of additions or removals).\n\n### Generating lists\n\nThe same list `[ 1; 3; 5; 7; 9 ]` can be generated in various ways.\n\n```fsharp\n[ 1; 3; 5; 7; 9 ]\n[ 1..2..9 ]\n[ for i in 0..4 -\u003e 2 * i + 1 ]\nList.init 5 (fun i -\u003e 2 * i + 1)\n```\n\nThe array `[| 1; 3; 5; 7; 9 |]` can be generated similarly:\n\n```fsharp\n[| 1; 3; 5; 7; 9 |]\n[| 1..2..9 |]\n[| for i in 0..4 -\u003e 2 * i + 1 |]\nArray.init 5 (fun i -\u003e 2 * i + 1)\n```\n\n### Functions on collections\n\nLists and arrays have comprehensive functions for manipulation.\n\n  - `List.map` transforms every element of the list (or array)\n  - `List.iter` iterates through a list and produces side effects\n\nThese and other functions are covered below. All these operations are also available for sequences. \n\n\u003ca name=\"Records\"\u003e\u003c/a\u003eRecords\n------------------\n\n*Records* represent simple aggregates of named values, optionally with members:\n\n```fsharp\n// Declare a record type\ntype Person = { Name : string; Age : int }\n\n// Create a value via record expression\nlet paul = { Name = \"Paul\"; Age = 28 }\n\n// 'Copy and update' record expression\nlet paulsTwin = { paul with Name = \"Jim\" }\n```\n\nRecords can be augmented with properties and methods:\n\n```fsharp\ntype Person with\n     member x.Info = (x.Name, x.Age)\n```\n\nRecords are essentially sealed classes with extra topping: default immutability, structural equality, and pattern matching support.\n\n```fsharp\nlet isPaul person =\n    match person with\n    | { Name = \"Paul\" } -\u003e true\n    | _ -\u003e false\n```\n\n\u003ca name=\"Recursive Functions\"\u003e\u003c/a\u003eRecursion\n----------------\n\nThe `rec` keyword is used together with the `let` keyword to define a recursive function:\n\n```fsharp\nlet rec fact x =\n    if x \u003c 1 then 1\n    else x * fact (x - 1)\n```\n\n*Mutually recursive* functions (those functions which call each other) are indicated by `and` keyword:\n\n```fsharp\nlet rec even x =\n   if x = 0 then true \n   else odd (x - 1)\n\nand odd x =\n   if x = 0 then false\n   else even (x - 1)\n```\n\n`rec` also can be used to define strings like this:\n\n```fsharp\nlet rec name = nameof name\n```\n\n\u003ca name=\"DiscriminatedUnions\"\u003e\u003c/a\u003eDiscriminated Unions\n--------------------\n\n*Discriminated unions* (DU) provide support for values that can be one of a number of named cases, each possibly with different values and types.\n\n```fsharp\ntype Tree\u003c'T\u003e =\n    | Node of Tree\u003c'T\u003e * 'T * Tree\u003c'T\u003e\n    | Leaf\n\n\nlet rec depth input =\n    match input with\n    | Node(l, _, r) -\u003e 1 + max (depth l) (depth r)\n    | Leaf -\u003e 0\n```\n\nF# Core has a few built-in discriminated unions for error handling, e.g., [Option](http://msdn.microsoft.com/en-us/library/dd233245.aspx) and [Result](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/results).\n\nUsing [Option](http://msdn.microsoft.com/en-us/library/dd233245.aspx):\n\n```fsharp\nlet optionPatternMatch input =\n    match input with\n    | Some i -\u003e printfn \"input is an int=%d\" i\n    | None -\u003e printfn \"input is missing\"\n\noptionPatternMatch (Some 1)\noptionPatternMatch None\n```\n\nUsing [Result](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/results):\n\n```fsharp\nlet resultPatternMatch input =\n    match input with\n    | Ok i -\u003e printfn \"Success with code %d\" i\n    | Error e -\u003e printfn \"Error with code %d\" e\n\nresultPatternMatch (Ok 0)\nresultPatternMatch (Error 1)\n```\n\nSingle-case discriminated unions are often used to create type-safe abstractions with pattern matching support:\n\n```fsharp\ntype OrderId = Order of string\n\n// Create a DU value\nlet orderId = Order \"12\"\n\n// Use pattern matching to deconstruct single-case DU\nlet (Order id) = orderId\n```\n\n\u003ca name=\"Exceptions\"\u003e\u003c/a\u003eExceptions\n----------\nThe `failwith` function throws an exception of type `Exception`.\n\n```fsharp\nlet divideFailwith x y =\n    if y = 0 then \n        failwith \"Divisor cannot be zero.\" \n        else x / y\n```\n\nException handling is done via `try/with` expressions.\n\n```fsharp\nlet divide x y =\n    try\n        Some (x / y)\n    with :? System.DivideByZeroException -\u003e \n        printfn \"Division by zero!\"\n        None\n```\n  \nThe `try/finally` expression enables you to execute clean-up code even if a block of code throws an exception. Here's an example which also defines custom exceptions.\n\n```fsharp\nexception InnerError of string\nexception OuterError of string\n  \nlet handleErrors x y =\n   try \n       try \n           if x = y then raise (InnerError(\"inner\"))\n           else raise (OuterError(\"outer\"))\n       with InnerError(str) -\u003e \n          printfn \"Error1 %s\" str\n   finally\n       printfn \"Always print this.\"\n```\n\n\u003ca name=\"ClassesAndInheritance\"\u003e\u003c/a\u003eClasses and Inheritance\n-----------------------\nThis example is a basic class with (1) local let bindings, (2) properties, (3) methods, and (4) static members.\n\n```fsharp\ntype Vector(x: float, y: float) =\n    let mag = sqrt(x * x + y * y)               // (1) - local let binding\n\n    member this.X = x                           // (2) property\n    member this.Y = y                           // (2) property\n    member this.Mag = mag                       // (2) property\n\n    member this.Scale(s) =                       // (3) method\n        Vector(x * s, y * s)\n\n    static member (+) (a : Vector, b : Vector) = // (4) static method\n        Vector(a.X + b.X, a.Y + b.Y)\n```\n\nCall a base class from a derived one:\n\n```fsharp\ntype Animal() =\n    member _.Rest() = ()\n           \ntype Dog() =\n    inherit Animal()\n    member _.Run() =\n        base.Rest()\n```\n\n\u003ca name=\"InterfacesAndObjectExpressions\"\u003e\u003c/a\u003eInterfaces and Object Expressions\n---------------------------------\nDeclare `IVector` interface and implement it in `Vector'`.\n\n```fsharp\ntype IVector =\n    abstract Scale : float -\u003e IVector\n\ntype Vector(x, y) =\n    interface IVector with\n        member __.Scale(s) =\n            Vector(x * s, y * s) :\u003e IVector\n            \n    member __.X = x\n    \n    member __.Y = y\n```\n\nAnother way of implementing interfaces is to use *object expressions*.\n\n```fsharp\ntype ICustomer =\n    abstract Name : string\n    abstract Age : int\n\nlet createCustomer name age =\n    { new ICustomer with\n        member __.Name = name\n        member __.Age = age }\n```\n\n\u003ca name=\"CastingAndConversions\"\u003e\u003c/a\u003eCasting and Conversions\n---------------\n\n```fsharp\nint 3.1415     // float to int = 3\nint \"3\"        // string to int = 3\nfloat 3        // int to float = 3.0\nfloat \"3.1415\" // string to float = 3.1415\nstring 3       // int to string = \"3\"\nstring 3.1415  // float to string = \"3.1415\"\n```\n\n*Upcasting* is denoted by `:\u003e` operator.\n\n```fsharp\nlet dog = Dog() \nlet animal = dog :\u003e Animal\n```\n\nIn many places type inference applies upcasting automatically:\n\n```fsharp\nlet exerciseAnimal (animal: Animal) = () \n\nlet dog = Dog()\n\nexerciseAnimal dog   // no need to upcast dog to Animal\n```\n\n*Dynamic downcasting* (`:?\u003e`) might throw an `InvalidCastException` if the cast doesn't succeed at runtime.\n\n```fsharp\nlet shouldBeADog = animal :?\u003e Dog\n```\n\n\u003ca name=\"ActivePatterns\"\u003e\u003c/a\u003eActive Patterns\n---------------\n\n*Complete active patterns*:\n\n```fsharp\nlet (|Even|Odd|) i = \n  if i % 2 = 0 then Even else Odd\n\nlet testNumber i =\n    match i with\n    | Even -\u003e printfn \"%d is even\" i\n    | Odd -\u003e printfn \"%d is odd\" i\n```\n\n*Parameterized, partial active patterns*:\n\n```fsharp\nlet (|DivisibleBy|_|) divisor n = \n  if n % divisor = 0 then Some DivisibleBy else None\n\nlet fizzBuzz input =\n    match input with\n    | DivisibleBy 3 \u0026 DivisibleBy 5 -\u003e \"FizzBuzz\" \n    | DivisibleBy 3 -\u003e \"Fizz\" \n    | DivisibleBy 5 -\u003e \"Buzz\" \n    | i -\u003e string i\n```\n\n*Partial active patterns* share the syntax of parameterized patterns but their active recognizers accept only one argument.\n\n\u003ca name=\"CompilerDirectives\"\u003e\u003c/a\u003eCompiler Directives\n-------------------\n\nLoad another F# source file into F# Interactive (`dotnet fsi`).\n\n```fsharp\n#load \"../lib/StringParsing.fs\"\n```\n\nReference a .NET package:\n\n```fsharp\n#r \"nuget: FSharp.Data\"                // latest non-beta version\n#r \"nuget: FSharp.Data,Version=4.2.2\"  // specific version\n```\n\nSpecifying a package source:\n\n```fsharp\n#i \"nuget: https://my-remote-package-source/index.json\"\n\n#i \"\"\"nuget: C:\\path\\to\\my\\local\\source\"\"\"\n```\n\nReference a specific .NET assembly file:\n\n```fsharp\n#r \"../lib/FSharp.Markdown.dll\"\n```\n\nInclude a directory in assembly search paths:\n\n```fsharp\n#I \"../lib\"\n#r \"FSharp.Markdown.dll\"\n```\n\nOther important directives are conditional execution in FSI (`INTERACTIVE`), conditional for compiled code (`COMPILED`) and querying current directory (`__SOURCE_DIRECTORY__`).\n\n```fsharp\n#if INTERACTIVE\nlet path = __SOURCE_DIRECTORY__ + \"../lib\"\n#else\nlet path = \"../../../lib\"\n#endif\n```\n\n\u003ca name=\"Acknowledgments\"\u003e\u003c/a\u003eAcknowledgments\n--------\n\nThanks goes to these people/projects:\n\n- [dungpa/fsharp-cheatsheet](https://github.com/dungpa/fsharp-cheatsheet)\n- [artag/fsharp-cheatsheet](https://github.com/artag/fsharp-cheatsheet)\n- [thriuin/fsharp-cheatsheet](https://github.com/thriuin/fsharp-cheatsheet)\n- [Succinct FSharp](https://dasdocs.com/fsharp/1-succinct-fsharp.html)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadelarsq%2Ffsharp-cheatsheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadelarsq%2Ffsharp-cheatsheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadelarsq%2Ffsharp-cheatsheet/lists"}