From 8b35146153c1cb9bd448bbbaee1219891baba190 Mon Sep 17 00:00:00 2001 From: Gustavo Leon <1261319+gusty@users.noreply.github.com> Date: Sun, 19 Nov 2023 18:25:35 +0100 Subject: [PATCH] Fix indentation --- docsrc/content/tutorial.fsx | 139 ++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 68 deletions(-) diff --git a/docsrc/content/tutorial.fsx b/docsrc/content/tutorial.fsx index 0a14cb579..9536d204d 100644 --- a/docsrc/content/tutorial.fsx +++ b/docsrc/content/tutorial.fsx @@ -3,7 +3,6 @@ // it to define helpers that you do not want to show in the documentation. #r @"../../src/FSharpPlus/bin/Release/netstandard2.0/FSharpPlus.dll" -#nowarn "0058" // We need to cheat a bit with indentation here. (** Introducing FSharpPlus @@ -20,12 +19,11 @@ Introducing FSharpPlus #r @"nuget: FSharpPlus" ``` *) -open FSharpPlus - -(** - Ignore warnings about F# metadata if any. +(*** hide ***) +module [] E1 = +(** Now we'll start with a quick overview of the features presented in F#+. ### Generic functions @@ -36,33 +34,35 @@ here's an example with map ([fmap](https://wiki.haskell.org/Functor *) -map string [|2;3;4;5|] -// val it : string [] = [|"2"; "3"; "4"; "5"|] + open FSharpPlus -map ((+) 9) (Some 3) -// val it : int option = Some 12 + map string [|2;3;4;5|] + // val it : string [] = [|"2"; "3"; "4"; "5"|] -open FSharpPlus.Data + map ((+) 9) (Some 3) + // val it : int option = Some 12 -map string (NonEmptyList.create 2 [3;4;5]) -// val it : NonEmptyList = {Head = "2"; Tail = ["3"; "4"; "5"];} + open FSharpPlus.Data + + map string (NonEmptyList.create 2 [3;4;5]) + // val it : NonEmptyList = {Head = "2"; Tail = ["3"; "4"; "5"];} (** They're also available for your own types as long as they contain the appropriated method with the expected signature *) -type Tree<'t> = - | Tree of 't * Tree<'t> * Tree<'t> - | Leaf of 't - static member Map (x:Tree<'a>, f) = - let rec loop f = function - | Leaf x -> Leaf (f x) - | Tree (x, t1, t2) -> Tree (f x, loop f t1, loop f t2) - loop f x - -map ((*) 10) (Tree(6, Tree(2, Leaf 1, Leaf 3), Leaf 9)) -// val it : Tree = Tree (60,Tree (20,Leaf 10,Leaf 30),Leaf 90) + type Tree<'t> = + | Tree of 't * Tree<'t> * Tree<'t> + | Leaf of 't + static member Map (x:Tree<'a>, f) = + let rec loop f = function + | Leaf x -> Leaf (f x) + | Tree (x, t1, t2) -> Tree (f x, loop f t1, loop f t2) + loop f x + + map ((*) 10) (Tree(6, Tree(2, Leaf 1, Leaf 3), Leaf 9)) + // val it : Tree = Tree (60,Tree (20,Leaf 10,Leaf 30),Leaf 90) (** Generic functions may be seen as an exotic thing in F# that only saves a few key strokes (map instead of List.map or Array.map) still they allow you to reach a higher abstraction level, using ad-hoc polymorphism. @@ -72,15 +72,15 @@ But more interesting is the use of operators. You can't prefix them with the mod Here you have a ready-to-use generic bind operator: ``>>=`` *) -let x = ["hello";" ";"world"] >>= (fun x -> Seq.toList x) -// val x : char list = ['h'; 'e'; 'l'; 'l'; 'o'; ' '; 'w'; 'o'; 'r'; 'l'; 'd'] + let x = ["hello";" ";"world"] >>= (fun x -> Seq.toList x) + // val x : char list = ['h'; 'e'; 'l'; 'l'; 'o'; ' '; 'w'; 'o'; 'r'; 'l'; 'd'] -let tryParseInt : string -> int option = tryParse -let tryDivide x n = if n = 0 then None else Some (x / n) + let tryParseInt : string -> int option = tryParse + let tryDivide x n = if n = 0 then None else Some (x / n) -let y = Some "20" >>= tryParseInt >>= tryDivide 100 -// val y : int option = Some 5 + let y = Some "20" >>= tryParseInt >>= tryDivide 100 + // val y : int option = Some 5 (** You have also the Kleisli composition (fish) operator: ``>=>`` @@ -88,41 +88,44 @@ You have also the Kleisli composition (fish) operator: ``>=>`` Which is becoming popular in F# after the [Railway Oriented Programming](https://www.google.ch/#q=railway+oriented+programming) tutorial series *) -let parseAndDivide100By = tryParseInt >=> tryDivide 100 + let parseAndDivide100By = tryParseInt >=> tryDivide 100 -let parsedAndDivide100By20 = parseAndDivide100By "20" // Some 5 -let parsedAndDivide100By0' = parseAndDivide100By "zero" // None -let parsedAndDivide100By0 = parseAndDivide100By "0" // None + let parsedAndDivide100By20 = parseAndDivide100By "20" // Some 5 + let parsedAndDivide100By0' = parseAndDivide100By "zero" // None + let parsedAndDivide100By0 = parseAndDivide100By "0" // None -let parseElement n = List.tryItem n >=> tryParseInt -let parsedElement = parseElement 2 ["0"; "1";"2"] + let parseElement n = List.tryItem n >=> tryParseInt + let parsedElement = parseElement 2 ["0"; "1";"2"] (** But don't forget the above used operators are generic, so we can change the type of our functions and we get a different functionality for free: *) (*** hide ***) -module E2 = +open FSharpPlus + +(*** hide ***) +module E2 = -let tryParseInt x : Choice = - match tryParse x with - | Some x -> Choice1Of2 x - | None -> Choice2Of2 ("Failed to parse " + x) + let tryParseInt x : Choice = + match tryParse x with + | Some x -> Choice1Of2 x + | None -> Choice2Of2 ("Failed to parse " + x) -let tryDivide x n = - if n = 0 then Choice2Of2 "Can't divide by zero" - else Choice1Of2 (x / n) + let tryDivide x n = + if n = 0 then Choice2Of2 "Can't divide by zero" + else Choice1Of2 (x / n) (** The test code remains unchanged, but we get a more interesting functionality *) -let parseAndDivide100By = tryParseInt >=> tryDivide 100 + let parseAndDivide100By = tryParseInt >=> tryDivide 100 -let parsedAndDivide100By20 = parseAndDivide100By "20" // Choice1Of2 5 -let parsedAndDivide100By0' = parseAndDivide100By "zero" // Choice2Of2 "Failed to parse zero" -let parsedAndDivide100By0 = parseAndDivide100By "0" // Choice2Of2 "Can't divide by zero" + let parsedAndDivide100By20 = parseAndDivide100By "20" // Choice1Of2 5 + let parsedAndDivide100By0' = parseAndDivide100By "zero" // Choice2Of2 "Failed to parse zero" + let parsedAndDivide100By0 = parseAndDivide100By "0" // Choice2Of2 "Can't divide by zero" (** @@ -130,9 +133,9 @@ let parsedAndDivide100By0 = parseAndDivide100By "0" // Choice2Of2 "Can't div Also when working with combinators, the generic applicative functor (space invaders) operator is very handy: ``<*>`` *) -let sumAllOptions = Some (+) <*> Some 2 <*> Some 10 // val sumAllOptions : int option = Some 12 + let sumAllOptions = Some (+) <*> Some 2 <*> Some 10 // val sumAllOptions : int option = Some 12 -let sumAllElemets = [(+)] <*> [10; 100] <*> [1; 2; 3] // int list = [11; 12; 13; 101; 102; 103] + let sumAllElemets = [(+)] <*> [10; 100] <*> [1; 2; 3] // int list = [11; 12; 13; 101; 102; 103] (** @@ -154,43 +157,43 @@ from https://github.com/ekmett/lens/wiki/Examples First, open F#+ Lens *) -open FSharpPlus.Lens + open FSharpPlus.Lens (** Now, you can read from lenses (``_2`` is a lens for the second component of a tuple) *) -let r1 = ("hello","world")^._2 -// val it : string = "world" + let r1 = ("hello","world")^._2 + // val it : string = "world" (** and you can write to lenses. *) -let r2 = setl _2 42 ("hello","world") -// val it : string * int = ("hello", 42) + let r2 = setl _2 42 ("hello","world") + // val it : string * int = ("hello", 42) (** Composing lenses for reading (or writing) goes in the order an imperative programmer would expect, and just uses ``(<<)``. *) -let r3 = ("hello",("world","!!!"))^.(_2 << _1) -// val it : string = "world" + let r3 = ("hello",("world","!!!"))^.(_2 << _1) + // val it : string = "world" -let r4 = setl (_2 << _1) 42 ("hello",("world","!!!")) -// val it : string * (int * string) = ("hello", (42, "!!!")) + let r4 = setl (_2 << _1) 42 ("hello",("world","!!!")) + // val it : string * (int * string) = ("hello", (42, "!!!")) (** You can make a Getter out of a pure function with ``to'``. *) -let r5 = "hello"^.to' length -// val it : int = 5 + let r5 = "hello"^.to' length + // val it : int = 5 (** You can easily compose a Getter with a Lens just using ``(<<)``. No explicit coercion is necessary. *) -let r6 = ("hello",("world","!!!"))^. (_2 << _2 << to' length) -// val it : int = 3 + let r6 = ("hello",("world","!!!"))^. (_2 << _2 << to' length) + // val it : int = 3 (** As we saw above, you can write to lenses and these writes can change the type of the container. ``(.->)`` is an infix alias for ``set``. *) -let r7 = _1 .-> "hello" <| ((),"world") -// val it : string * string = ("hello", "world") + let r7 = _1 .-> "hello" <| ((),"world") + // val it : string * string = ("hello", "world") (** It can be used in conjunction with ``(|>)`` for familiar von Neumann style assignment syntax: *) -let r8 = ((), "world") |> _1 .-> "hello" -// val it : string * string = ("hello", "world") + let r8 = ((), "world") |> _1 .-> "hello" + // val it : string * string = ("hello", "world") (** Conversely view, can be used as an prefix alias for ``(^.)``. *) -let r9 = view _2 (10,20) -// val it : int = 20 + let r9 = view _2 (10,20) + // val it : int = 20 (**