Introduktion till FSharpPlus
Ladda ner binärer från Nuget.
- Öppna en F# skriptfil eller interaktiv F# prompt, referera till biblioteket och öppna namnrymd
1: 2: |
|
Ignorera varningar om F# metadata om några.
Vi kan nu starta med en snabb tur av de features som finns i F#+.
Generiska funktioner
De finns automatiskt tillgängliga när du har öppnat FSharpPlus namnrymd
här är ett exempel med map
(fmap för Haskelliter, Select för Csharpare):
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: |
|
Dessa funktioer finns också tillgängliga för dina egna typer så länge de innehåller metoder med förväntade signaturer
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: |
|
Generiska funktioner ser kanske exotiska ut med F#-ögon, som enbart sparar några få tangenttryckningar (map
istället för List.map
eller Array.map
). Det de däremot gör är att tillåta dig nå en högre abstraktionsnivå genom att använda ad-hoc polymorphism.
Ännu mer intressant är användningen av operatorer. Du kan inte prefixa dem med den modul de tillhör och förvänta dig att samma operator den fungerar för flera typer i samma utrymme. Ett exempel är att många F#-bibliotek definierar bind operator (>>=)
men att dessa inte går att använda samtidigt utan att behöva lägga till ett prefix t.ex. State.(>>=)
och Reader.(>>=)
vilket gör att nyttan av operatorn försvinner.
Här har du en färdig att använda generisk bind operator: >>=
1: 2: 3: 4: 5: 6: 7: 8: 9: |
|
Du har också Kleislikompositionen familiärt kallad fiskoperatorn: >=>
Denna operator är populär inom F# tack vare Railway Oriented Programming.
1: 2: 3: 4: 5: 6: 7: 8: |
|
Glöm inte bort att ovan använda operatorer är generiska, varför vi kan ändra på typen av våra funktioner och få annorlunda funktionalitet gratis:
Testkoden är oförändrad, men vi får mer intressant funktionalitet
1: 2: 3: 4: 5: |
|
När vi arbetar med kombinatorer är den generiska applikativa functoroperatorn (space invaders) väldigt praktisk: <*>
1: 2: 3: |
|
För mer detaljer och funktionalitet, se generiska operatorer och funktioner
Här är alla generiska operatorer och funktioner
Och här är en kort förklaring av Functor, Applicativ och Monad-abstraktionerna med kodexempel.
Lins
Från https://github.com/ekmett/lens/wiki/Examples
Först, öppna F#+ Lens
1:
|
|
Nu kan du läsa från linser (_2
är en lins för den andra komponenten av en tupel)
1: 2: |
|
och du kan skriva till linser.
1: 2: |
|
Att knyta ihop linser för att läsa (eller skriva) går i den ordning som en imperativ programmerare skulle förvänta sig: använder sig av (<<)
.
1: 2: 3: 4: 5: |
|
Du kan också göra en läsfunktion av en ren funktion genom att använda to'
.
1: 2: |
|
Du kan enkelt komponera läsfunktioner med linser genom att använda (<<)
.
1: 2: |
|
Som vi såg ovan, kan du skriva till linser och dessa uppdateringar förändrar vilken typ behållaren har. (.->)
är ett infix alias för set
.
1: 2: |
|
Den kan avnändas tillsammans med (|>)
för en bekant von Neumann-stil av tilldelningssyntax:
1: 2: |
|
Omvänt kan view användas som ett prefix alias för (^.)
.
1: 2: |
|
För mer detaljer:
Här är en full genomgång av liner och all annan optik
Ta dig en titt på alla linsfunktioner
val string : value:'T -> string
--------------------
type string = System.String
module NonEmptyList
from FSharpPlus.Data
--------------------
type NonEmptyList<'t> =
{ Head: 't
Tail: 't list }
interface IReadOnlyList<'t>
interface IReadOnlyCollection<'t>
interface IEnumerable
interface IEnumerable<'t>
member GetSlice : (int option * int option -> NonEmptyList<'t>)
member Item : (int -> 't)
member Length : int
static member Choice : source:NonEmptyList<'Alt<'T>> -> 'Alt<'T> (requires member IsAltLeftZero and member ( <|> ))
static member Duplicate : s:NonEmptyList<'a> * _impl:Duplicate -> NonEmptyList<NonEmptyList<'a>>
static member Extract : NonEmptyList<'t> -> 't
...
union case Tree.Tree: 't * Tree<'t> * Tree<'t> -> Tree<'t>
--------------------
type Tree<'t> =
| Tree of 't * Tree<'t> * Tree<'t>
| Leaf of 't
static member Map : x:Tree<'a> * f:('a -> 'a0) -> Tree<'a0>
module Map
from FSharpPlus
--------------------
module Map
from Microsoft.FSharp.Collections
--------------------
type Map<'Key,'Value (requires comparison)> =
interface IReadOnlyDictionary<'Key,'Value>
interface IReadOnlyCollection<KeyValuePair<'Key,'Value>>
interface IEnumerable
interface IComparable
interface IEnumerable<KeyValuePair<'Key,'Value>>
interface ICollection<KeyValuePair<'Key,'Value>>
interface IDictionary<'Key,'Value>
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
member Add : key:'Key * value:'Value -> Map<'Key,'Value>
member ContainsKey : key:'Key -> bool
...
--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
module Seq
from FSharpPlus.Data
--------------------
module Seq
from FSharpPlus.Operators
--------------------
module Seq
from FSharpPlus
--------------------
module Seq
from Microsoft.FSharp.Collections
val int : value:'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
val option : f:('g -> 'h) -> n:'h -> _arg1:'g option -> 'h
--------------------
type 'T option = Option<'T>
module List
from FSharpPlus.Data
--------------------
module List
from FSharpPlus
--------------------
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IReadOnlyList<'T>
interface IReadOnlyCollection<'T>
interface IEnumerable
interface IEnumerable<'T>
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
...
from Tutorial
module Choice
from FSharpPlus
--------------------
type Choice<'T1,'T2> =
| Choice1Of2 of 'T1
| Choice2Of2 of 'T2
--------------------
type Choice<'T1,'T2,'T3> =
| Choice1Of3 of 'T1
| Choice2Of3 of 'T2
| Choice3Of3 of 'T3
--------------------
type Choice<'T1,'T2,'T3,'T4> =
| Choice1Of4 of 'T1
| Choice2Of4 of 'T2
| Choice3Of4 of 'T3
| Choice4Of4 of 'T4
--------------------
type Choice<'T1,'T2,'T3,'T4,'T5> =
| Choice1Of5 of 'T1
| Choice2Of5 of 'T2
| Choice3Of5 of 'T3
| Choice4Of5 of 'T4
| Choice5Of5 of 'T5
--------------------
type Choice<'T1,'T2,'T3,'T4,'T5,'T6> =
| Choice1Of6 of 'T1
| Choice2Of6 of 'T2
| Choice3Of6 of 'T3
| Choice4Of6 of 'T4
| Choice5Of6 of 'T5
| Choice6Of6 of 'T6
--------------------
type Choice<'T1,'T2,'T3,'T4,'T5,'T6,'T7> =
| Choice1Of7 of 'T1
| Choice2Of7 of 'T2
| Choice3Of7 of 'T3
| Choice4Of7 of 'T4
| Choice5Of7 of 'T5
| Choice6Of7 of 'T6
| Choice7Of7 of 'T7
from FSharpPlus