From 0e93ae96805b9aa3f0265ed057dee24607161853 Mon Sep 17 00:00:00 2001 From: Matt Thornton Date: Thu, 15 Jul 2021 16:29:17 +0100 Subject: [PATCH 1/2] Add test for Lift3 for Free. --- tests/FSharpPlus.Tests/Free.fs | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/FSharpPlus.Tests/Free.fs b/tests/FSharpPlus.Tests/Free.fs index f3e82cba1..f82eb00e8 100644 --- a/tests/FSharpPlus.Tests/Free.fs +++ b/tests/FSharpPlus.Tests/Free.fs @@ -316,3 +316,39 @@ module Fold = |> Identity.run areStEqual (Ok { Id = FooId "1"; Name = "test" }) response + +module Lift3 = + + type Instruction<'next> = + | Read of int * (string -> 'next) + static member Map(i, f) = + match i with + | Read (x, next) -> Read(x, next >> f) + + let read x = Read(x, id) |> Free.liftF + + type ApplicativeBuilder<'a>() = + inherit MonadFxStrictBuilder<'a>() + + member inline _.BindReturn(x, f) = map f x + + let applicative<'a> = ApplicativeBuilder<'a>() + + [] + let ``should be able to use applicative CE which requires Lift3`` () = + let program = + applicative { + let! a = read 1 + and! b = read 2 + and! c = read 3 + return a, b, c + } + + let result = + program + |> Free.fold + (function + | Read (i, next) -> i |> string |> next |> result) + |> Identity.run + + areStEqual result ("1", "2", "3") From 8d3003dd27d31f738370678a2786f9f9ae0cf6e5 Mon Sep 17 00:00:00 2001 From: Gustavo Leon <1261319+gusty@users.noreply.github.com> Date: Thu, 8 Sep 2022 10:41:52 +0200 Subject: [PATCH 2/2] Fix Free.map3 --- src/FSharpPlus/Data/Free.fs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/FSharpPlus/Data/Free.fs b/src/FSharpPlus/Data/Free.fs index 4a9f13b63..216acf368 100644 --- a/src/FSharpPlus/Data/Free.fs +++ b/src/FSharpPlus/Data/Free.fs @@ -62,11 +62,11 @@ module Free = loop y x let inline map3 (f: 'T->'U->'V->'W) (x: Free<'``Functor<'T>``,'T>) (y: Free<'``Functor<'U>``,'U>) (z: Free<'``Functor<'V>``,'V>) : Free<'``Functor<'W>``,'W> = - let rec loop (y: Free<_,_>) (x: Free<_,_>) (z: Free<_,_>) = + let rec loop (y: Free<_,_>) (z: Free<_,_>) (x: Free<_,_>) = match run x with - | Pure x -> map2<'U,'V,'W,'``Functor<'U>``,'``Functor,'U>>``,'``Functor,'V>>``,'``Functor,'W>>``,'``Functor<'V>``,'``Functor<'W>``> (f x) y z : Free<'``Functor<'W>``,'W> - | Roll (x: ^``Functor,'T>>``) -> Roll (Map.Invoke (loop y: Free<'``Functor<'T>``,'T> -> _) x: '``Functor,'W>>``) - loop y x z + | Pure x -> map2<'U,'V,'W,'``Functor<'U>``,'``Functor,'U>>``,'``Functor,'W>>``,'``Functor,'V>>``,'``Functor<'V>``,'``Functor<'W>``> (f x) y z : Free<'``Functor<'W>``,'W> + | Roll (x: ^``Functor,'T>>``) -> Roll (Map.Invoke (loop y z: Free<'``Functor<'T>``,'T> -> _) x: '``Functor,'W>>``) + loop y z x /// Folds the Free structure into a Monad let inline fold (f: '``Functor<'T>`` -> '``Monad<'T>``) (x: Free<'``Functor<'U>``,'U>) : '``Monad<'U>`` = @@ -105,4 +105,4 @@ type Free<'``functor<'t>``,'t> with static member Delay (x: unit -> Free<'``Functor<'T>``,'T>) = x () -#endif \ No newline at end of file +#endif