|
| 1 | +module Pos34 |
| 2 | + |
| 3 | +// From https://github.com/dotnet/fsharp/issues/4171#issuecomment-528063764 |
| 4 | +// This case is where the type gets labelled as Sealed |
| 5 | +// This case compiles without complaint |
| 6 | +// |
| 7 | +// See also neg120.fs |
| 8 | +open System.Threading.Tasks |
| 9 | + |
| 10 | +[<Sealed>] |
| 11 | +type Id<'t> (v: 't) = |
| 12 | + let value = v |
| 13 | + member __.getValue = value |
| 14 | + |
| 15 | +[<RequireQualifiedAccess>] |
| 16 | +module Id = |
| 17 | + let run (x: Id<_>) = x.getValue |
| 18 | + let map f (x: Id<_>) = Id (f x.getValue) |
| 19 | + let create x = Id x |
| 20 | + |
| 21 | + |
| 22 | +type Bind = |
| 23 | + static member (>>=) (source: Lazy<'T> , f: 'T -> Lazy<'U> ) = lazy (f source.Value).Value : Lazy<'U> |
| 24 | + static member (>>=) (source: Task<'T> , f: 'T -> Task<'U> ) = source.ContinueWith(fun (x: Task<_>) -> f x.Result).Unwrap () : Task<'U> |
| 25 | + static member (>>=) (source , f: 'T -> _ ) = Option.bind f source : option<'U> |
| 26 | + static member (>>=) (source , f: 'T -> _ ) = async.Bind (source, f) |
| 27 | + static member (>>=) (source : Id<_> , f: 'T -> _ ) = f source.getValue : Id<'U> |
| 28 | + |
| 29 | + static member inline Invoke (source: '``Monad<'T>``) (binder: 'T -> '``Monad<'U>``) : '``Monad<'U>`` = |
| 30 | + let inline call (_mthd: 'M, input: 'I, _output: 'R, f) = ((^M or ^I or ^R) : (static member (>>=) : _*_ -> _) input, f) |
| 31 | + call (Unchecked.defaultof<Bind>, source, Unchecked.defaultof<'``Monad<'U>``>, binder) |
| 32 | + |
| 33 | +let inline (>>=) (x: '``Monad<'T>``) (f: 'T->'``Monad<'U>``) : '``Monad<'U>`` = Bind.Invoke x f |
| 34 | + |
| 35 | +type Return = |
| 36 | + static member inline Invoke (x: 'T) : '``Applicative<'T>`` = |
| 37 | + let inline call (mthd: ^M, output: ^R) = ((^M or ^R) : (static member Return : _*_ -> _) output, mthd) |
| 38 | + call (Unchecked.defaultof<Return>, Unchecked.defaultof<'``Applicative<'T>``>) x |
| 39 | + |
| 40 | + static member Return (_: Lazy<'a> , _: Return ) = fun x -> Lazy<_>.CreateFromValue x : Lazy<'a> |
| 41 | + static member Return (_: 'a Task , _: Return ) = fun x -> Task.FromResult x : 'a Task |
| 42 | + static member Return (_: option<'a> , _: Return ) = fun x -> Some x : option<'a> |
| 43 | + static member Return (_: 'a Async , _: Return ) = fun (x: 'a) -> async.Return x |
| 44 | + static member Return (_: 'a Id , _: Return ) = fun (x: 'a) -> Id x |
| 45 | + |
| 46 | +let inline result (x: 'T) : '``Functor<'T>`` = Return.Invoke x |
| 47 | + |
| 48 | + |
| 49 | +type TypeT<'``monad<'t>``> = TypeT of obj |
| 50 | +type Node<'``monad<'t>``,'t> = A | B of 't * TypeT<'``monad<'t>``> |
| 51 | + |
| 52 | +let inline wrap (mit: 'mit) = |
| 53 | + let _mnil = (result Unchecked.defaultof<'t> : 'mt) >>= fun (_:'t) -> (result Node<'mt,'t>.A ) : 'mit |
| 54 | + TypeT mit : TypeT<'mt> |
| 55 | + |
| 56 | +let inline unwrap (TypeT mit : TypeT<'mt>) = |
| 57 | + let _mnil = (result Unchecked.defaultof<'t> : 'mt) >>= fun (_:'t) -> (result Node<'mt,'t>.A ) : 'mit |
| 58 | + unbox mit : 'mit |
| 59 | + |
| 60 | +let inline empty () = wrap ((result Node<'mt,'t>.A) : 'mit) : TypeT<'mt> |
| 61 | + |
| 62 | +let inline concat l1 l2 = |
| 63 | + let rec loop (l1: TypeT<'mt>) (lst2: TypeT<'mt>) = |
| 64 | + let (l1, l2) = unwrap l1, unwrap lst2 |
| 65 | + TypeT (l1 >>= function A -> l2 | B (x: 't, xs) -> ((result (B (x, loop xs lst2))) : 'mit)) |
| 66 | + loop l1 l2 : TypeT<'mt> |
| 67 | + |
| 68 | + |
| 69 | +let inline bind f (source: TypeT<'mt>) : TypeT<'mu> = |
| 70 | + // let _mnil = (result Unchecked.defaultof<'t> : 'mt) >>= fun (_: 't) -> (result Unchecked.defaultof<'u>) : 'mu |
| 71 | + let rec loop f input = |
| 72 | + TypeT ( |
| 73 | + (unwrap input : 'mit) >>= function |
| 74 | + | A -> result <| (A : Node<'mu,'u>) : 'miu |
| 75 | + | B (h:'t, t: TypeT<'mt>) -> |
| 76 | + let res = concat (f h: TypeT<'mu>) (loop f t) |
| 77 | + unwrap res : 'miu) |
| 78 | + loop f source : TypeT<'mu> |
| 79 | + |
| 80 | + |
| 81 | +let inline map (f: 'T->'U) (x: '``Monad<'T>`` ) = Bind.Invoke x (f >> Return.Invoke) : '``Monad<'U>`` |
| 82 | + |
| 83 | + |
| 84 | +let inline unfold (f:'State -> '``M<('T * 'State) option>``) (s:'State) : TypeT<'MT> = |
| 85 | + let rec loop f s = f s |> map (function |
| 86 | + | Some (a, s) -> B (a, loop f s) |
| 87 | + | None -> A) |> wrap |
| 88 | + loop f s |
| 89 | + |
| 90 | +let inline create (al: '``Monad<list<'T>>``) : TypeT<'``Monad<'T>``> = |
| 91 | + unfold (fun i -> map (fun (lst:list<_>) -> if lst.Length > i then Some (lst.[i], i+1) else None) al) 0 |
| 92 | + |
| 93 | +let inline run (lst: TypeT<'MT>) : '``Monad<list<'T>>`` = |
| 94 | + let rec loop acc x = unwrap x >>= function |
| 95 | + | A -> result (List.rev acc) |
| 96 | + | B (x, xs) -> loop (x::acc) xs |
| 97 | + loop [] lst |
| 98 | + |
| 99 | +let c0 = create (Id ([1..10])) |
| 100 | +let res0 = c0 |> run |> create |> run |
| 101 | + |
0 commit comments