Skip to content

Commit 97f3c4b

Browse files
committed
Merge branch 'master' into v1.4
2 parents 25158ad + 9844fcc commit 97f3c4b

26 files changed

+633
-194
lines changed

RELEASE_NOTES.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
#### 1.4.0 - February 22 2023
2+
- Additional Alternatives available (functions, error monads)
3+
- More IReadOnlyDictionary functions
4+
- Bug fixes in Map as FoldIndexable and missing <*> for IDictionary and IReadOnlyDictionary
5+
- Deprecate IReadOnlyDictionary.map
6+
- Guid to/from bytes conversion
7+
18
#### 1.3.3 - February 5 2023
29
- Fix missing zero overload for voption
310
- Add (>>=) and (>=>) to ReaderT

RELEASE_NOTES.txt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
Release Notes for FSharpPlus 1.3.3 - February 5 2023
2-
-----------------------------------------------------
1+
Release Notes for FSharpPlus 1.4.0 - February 22 2023
2+
------------------------------------------------------
33

4-
Fix missing zero overload for voption
5-
Add (>>=) and (>=>) to ReaderT
6-
Add ValueOption.toOption
7-
Deprecate (<**>)
4+
Additional Alternatives available (functions, error monads)
5+
More IReadOnlyDictionary functions
6+
Bug fixes in Map as FoldIndexable and missing <*> for IDictionary and IReadOnlyDictionary
7+
Deprecate IReadOnlyDictionary.map
8+
Guid to/from bytes conversion

docsrc/content/abstraction-alternative.fsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,17 @@ From .Net/F#
5959
- ``option<'T>``
6060
- ``array<'T>``
6161
- ``seq<'T>``
62+
- ``'T -> 'Alternative``
6263
6364
From F#+
6465
6566
- [``ReaderT<'R, 'MonadPlus<'T>>``](type-readert.html)
6667
- [``WriterT<'MonadPlus<'T * 'Monoid>>``](type-writert.html)
6768
- [``StateT<'S,'MonadPlus<'T * 'S>>``](type-statet.html)
69+
- [``OptionT<'MonadPlus<option<'T>>>``](type-optiont.html)
70+
- [``ValueOptionT<'MonadPlus<voption<'T>>>``](type-valueoptiont.html)
71+
- [``ResultT<'MonadPlus<Result<'T,'Monoid>>>``](type-resultt.html)
72+
- [``ChoiceT<'MonadPlus<Choice<'T,'Monoid>>>``](type-choicet.html)
6873
- [``Compose<'AlternativeF<'AlternativeG<'T>>>``](type-compose.html)
6974
- [``DList<'T>``](type-dlist.html)
7075
- [``ZipList<'S>``](type-ziplist.html)
@@ -157,4 +162,4 @@ let r6 = map string (Just 6)
157162
// But not always the Monoidal behaviour is the same
158163

159164
let r3 = Some 2 ++ Some 1 // addition => Some 3
160-
let r2 = Some 2 <|> Some 1 // first success => Some 2
165+
let r2 = Some 2 <|> Some 1 // first success => Some 2

docsrc/content/abstraction-applicative.fsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ From F#
6666
- ``Choice<'T,'U>``
6767
- ``KeyValuePair<'Key,'T>``
6868
- ``'Monoid * 'T``
69-
- ``'ValueTuple<Monoid, 'T>``
69+
- ``ValueTuple<'Monoid, 'T>``
7070
- ``Task<'T>``
7171
- ``ValueTask<'T>``
7272
- ``'R->'T``
@@ -107,6 +107,13 @@ Restricted:
107107
- ``Set<'T>``
108108
- ``IEnumerator<'T>``
109109
110+
Only for <*> operation:
111+
- ``Map<'Key, 'T>``
112+
- ``Dictionary<'Key, 'T>``
113+
- ``IDictionary<'Key, 'T>``
114+
- ``IReadOnlyDictionary<'Key, 'T>``
115+
116+
110117
[Suggest another](https://github.com/fsprojects/FSharpPlus/issues/new) concrete implementation
111118
112119
Examples

docsrc/content/type-free.fsx

Lines changed: 107 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,121 @@
33
// it to define helpers that you do not want to show in the documentation.
44
#r @"../../src/FSharpPlus/bin/Release/net45/FSharpPlus.dll"
55
(**
6-
TO-DO Add some docs here !
7-
=========================
6+
Free<'Functor<'T>, 'T>
7+
======================
8+
9+
This type is an implementation of the [Free Monad](https://www.google.com/search?q=free+monad) which is generic to any [Functor](abstraction-functor.html).
10+
11+
The Free Monad is used typically to describe a pure program at high level and separately write different interpreters for it.
12+
13+
Related Types
14+
-------------
15+
16+
- [Coproduct](type-coproduct.html): A [Functor](abstraction-functor.html) used in conjunction with the Free Monad to combine different instruction sets.
17+
18+
19+
820
921
Examples
1022
--------
23+
24+
Free monad-interpreter in F# from [Mark Seemann's blog](https://blog.ploeh.dk/2017/07/17/a-pure-command-line-wizard) but encoded with Free.
25+
1126
*)
1227

28+
29+
1330
(**
1431
```f#
1532
#r @"nuget: FSharpPlus"
1633
```
1734
*)
1835

19-
open FSharpPlus
36+
open System
37+
open FSharpPlus
38+
open FSharpPlus.Data
39+
40+
41+
type CommandLineInstruction<'t> =
42+
| ReadLine of (string -> 't)
43+
| WriteLine of string * 't
44+
with static member Map (x, f) =
45+
match x with
46+
| ReadLine g -> ReadLine (f << g)
47+
| WriteLine (s, g) -> WriteLine (s, f g)
48+
49+
let readLine = Free.liftF (ReadLine id)
50+
let writeLine s = Free.liftF (WriteLine (s, ()))
51+
52+
53+
let rec interpretCommandLine = Free.run >> function
54+
| Pure x -> x
55+
| Roll (ReadLine next) -> Console.ReadLine () |> next |> interpretCommandLine
56+
| Roll (WriteLine (s, next)) ->
57+
Console.WriteLine s
58+
next |> interpretCommandLine
59+
60+
let rec readQuantity = monad {
61+
do! writeLine "Please enter number of diners:"
62+
let! l = readLine
63+
match tryParse l with
64+
| Some dinerCount -> return dinerCount
65+
| None ->
66+
do! writeLine "Not an integer."
67+
return! readQuantity }
68+
69+
let rec readDate = monad {
70+
do! writeLine "Please enter your desired date:"
71+
let! l = readLine
72+
match DateTimeOffset.TryParse l with
73+
| true, dt -> return dt
74+
| _ ->
75+
do! writeLine "Not a date."
76+
return! readDate }
77+
78+
let readName = monad {
79+
do! writeLine "Please enter your name:"
80+
return! readLine }
81+
82+
let readEmail = monad {
83+
do! writeLine "Please enter your email address:"
84+
return! readLine }
85+
86+
87+
type Reservation = {
88+
Date : DateTimeOffset
89+
Name : string
90+
Email : string
91+
Quantity : int }
92+
with static member Create (Quantity, Date, Name, Email) = { Date = Date; Name = Name; Email = Email; Quantity = Quantity }
93+
94+
let readReservationRequest =
95+
curryN Reservation.Create
96+
<!> readQuantity
97+
<*> readDate
98+
<*> readName
99+
<*> readEmail
100+
101+
102+
103+
let mainFunc () =
104+
readReservationRequest
105+
>>= (writeLine << (sprintf "%A"))
106+
|> interpretCommandLine
107+
0
108+
109+
110+
(**
111+
More reading
112+
------------
113+
114+
- Highly recommended Matt Thornton's blog [Grokking Free monads](https://dev.to/choc13/grokking-free-monads-9jd) and [Interpreting Free Monads](https://dev.to/choc13/interpreting-free-monads-3l3e).
115+
It contains examples using F#+ and an explanation from scratch.
116+
117+
- Mark Seemann's blog has an [article series](https://blog.ploeh.dk/2017/06/27/pure-times/) which ends
118+
up describing Free Monads although he doesn't use F#+ and therefore either repeats boilerplate code or switches to Haskell.
119+
Anyways some code from those series (like the above fragment) can be found in [our test suite for Free](https://github.com/fsprojects/FSharpPlus/blob/master/tests/FSharpPlus.Tests/Free.fs) simplified using Free and Coproduct types.
120+
121+
- Scott Wlaschin's [13 ways of looking at a turtle](https://fsharpforfunandprofit.com/posts/13-ways-of-looking-at-a-turtle) is also a series which ends up defining a Free Monad, without using F#+ but with boilerplate code instead.
122+
123+
*)

src/FSharpPlus/Control/Alternative.fs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,16 @@ type Empty =
2424
static member Empty ([<Optional>]_output: option<'T> , [<Optional>]_mthd: Empty ) = None : option<'T>
2525
static member Empty ([<Optional>]_output: voption<'T> , [<Optional>]_mthd: Empty ) = ValueNone : voption<'T>
2626
static member Empty ([<Optional>]_output: list<'T> , [<Optional>]_mthd: Empty ) = [ ] : list<'T>
27-
static member Empty ([<Optional>]_output: 'T [] , [<Optional>]_mthd: Empty ) = [||] : 'T []
27+
static member Empty ([<Optional>]_output: 'T [] , [<Optional>]_mthd: Empty ) = [||] : 'T []
2828

2929
static member inline Invoke () : '``Alternative<'T>`` =
3030
let inline call (mthd: ^M, output: ^R) = ((^M or ^R) : (static member Empty : _*_ -> _) output, mthd)
3131
call (Unchecked.defaultof<Empty>, Unchecked.defaultof<'``Alternative<'T>``> )
3232

3333
static member inline InvokeOnInstance () : '``Alternative<'T>`` = (^``Alternative<'T>`` : (static member Empty : ^``Alternative<'T>``) ()) : '``Alternative<'T>``
3434

35+
type Empty with
36+
static member inline Empty ([<Optional>]_output: 'R -> '``Alternative<'T>``, [<Optional>]_mthd: Empty) = (fun _ -> Empty.Invoke ()) : 'R -> '``Alternative<'T>``
3537

3638
type Append =
3739
inherit Default1
@@ -53,6 +55,8 @@ type Append =
5355
let inline call (mthd: ^M, input1: ^I, input2: ^I) = ((^M or ^I) : (static member ``<|>`` : _*_*_ -> _) input1, input2, mthd)
5456
call (Unchecked.defaultof<Append>, x, y)
5557

58+
type Append with
59+
static member inline ``<|>`` (x: 'R -> '``Alt<'T>`` , y , [<Optional>]_mthd: Append ) = fun r -> Append.Invoke (x r) (y r)
5660

5761

5862
type IsAltLeftZero =

src/FSharpPlus/Control/Applicative.fs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ type Apply =
5454
| true, vx -> dct.Add (k, vf vx)
5555
| _ -> ()
5656
dct
57+
58+
static member ``<*>`` (f: IDictionary<'Key,_>, x: IDictionary<'Key,'T> , [<Optional>]_output: IDictionary<'Key,'U> , [<Optional>]_mthd: Apply) : IDictionary<'Key,'U> =
59+
let dct = Dictionary ()
60+
for KeyValue(k, vf) in f do
61+
match x.TryGetValue k with
62+
| true, vx -> dct.Add (k, vf vx)
63+
| _ -> ()
64+
dct :> IDictionary<'Key,'U>
65+
66+
static member ``<*>`` (f: IReadOnlyDictionary<'Key,_>, x: IReadOnlyDictionary<'Key,'T> , [<Optional>]_output: IReadOnlyDictionary<'Key,'U> , [<Optional>]_mthd: Apply) : IReadOnlyDictionary<'Key,'U> =
67+
let dct = Dictionary ()
68+
for KeyValue(k, vf) in f do
69+
match x.TryGetValue k with
70+
| true, vx -> dct.Add (k, vf vx)
71+
| _ -> ()
72+
dct :> IReadOnlyDictionary<'Key,'U>
73+
5774
#if !FABLE_COMPILER
5875
static member ``<*>`` (f: Expr<'T->'U>, x: Expr<'T>, [<Optional>]_output: Expr<'U>, [<Optional>]_mthd: Apply) = Expr.Cast<'U> (Expr.Application (f, x))
5976
#endif

src/FSharpPlus/Control/Converter.fs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ type OfBytes =
4949
static member OfBytes (_: int64 , _: OfBytes) = fun (x, i, e) -> BitConverter.ToInt64 (x, i, e)
5050
static member OfBytes (_: float32, _: OfBytes) = fun (x, i, e) -> BitConverter.ToSingle (x, i, e)
5151

52-
static member OfBytes (_: string , _: OfBytes) = fun (x, i, _) -> BitConverter.ToString (x, i)
52+
static member OfBytes (_: string , _: OfBytes) = fun (x, i, _) -> BitConverter.ToString (x, i)
53+
static member OfBytes (_: Guid , _: OfBytes) = fun (x, i, e) -> BitConverter.ToGuid (x, i, e)
5354

5455
static member OfBytes (_: uint16 , _: OfBytes) = fun (x, i, e) -> BitConverter.ToUInt16 (x, i, e)
5556
static member OfBytes (_: uint32 , _: OfBytes) = fun (x, i, e) -> BitConverter.ToUInt32 (x, i, e)
@@ -70,6 +71,7 @@ type ToBytes =
7071
static member ToBytes (x: int64 , e, _: ToBytes) = BitConverter.GetBytes (x, BitConverter.IsLittleEndian = e)
7172
static member ToBytes (x: float32, e, _: ToBytes) = BitConverter.GetBytes (x, BitConverter.IsLittleEndian = e)
7273
static member ToBytes (x: string , _, _: ToBytes) = Array.map byte (x.ToCharArray ())
74+
static member ToBytes (x: Guid , e, _: ToBytes) = BitConverter.GetBytes (x, BitConverter.IsLittleEndian = e)
7375
static member ToBytes (x: uint16 , e, _: ToBytes) = BitConverter.GetBytes (x, BitConverter.IsLittleEndian = e)
7476
static member ToBytes (x: uint32 , e, _: ToBytes) = BitConverter.GetBytes (x, BitConverter.IsLittleEndian = e)
7577
static member ToBytes (x: uint64 , e, _: ToBytes) = BitConverter.GetBytes (x, BitConverter.IsLittleEndian = e)

src/FSharpPlus/Control/Functor.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ type Map with
129129
static member Map ((x: NonEmptySeq<_> , f: 'T->'U), _mthd: Default2) = NonEmptySeq.map f x : NonEmptySeq<'U>
130130
static member Map ((x: IEnumerator<_> , f: 'T->'U), _mthd: Default2) = Enumerator.map f x : IEnumerator<'U>
131131
static member Map ((x: IDictionary<_,_> , f: 'T->'U), _mthd: Default2) = Dict.map f x : IDictionary<'Key,'U>
132-
static member Map ((x: IReadOnlyDictionary<_,_>, f: 'T->'U), _mthd: Default2) = IReadOnlyDictionary.map f x : IReadOnlyDictionary<'Key,_>
132+
static member Map ((x: IReadOnlyDictionary<_,_>, f: 'T->'U), _mthd: Default2) = IReadOnlyDictionary.mapValues f x : IReadOnlyDictionary<'Key,_>
133133
static member Map ((x: IObservable<'T> , f: 'T->'U), _mthd: Default2) = Observable.map f x : IObservable<'U>
134134
#if !FABLE_COMPILER
135135
static member Map ((x: Nullable<_> , f: 'T->'U), _mthd: Default2) = Nullable.map f x : Nullable<'U>

0 commit comments

Comments
 (0)