(后来的访问者:这个问题的两个答案都给出了很好的见解,如果你感兴趣的话,你应该把它们都读出来,我只能把它作为SO的限制除外)
从我在网上找到的关于延续monad的所有讨论,他们要么提到它如何与一些琐碎的例子一起使用,要么他们解释它是一个基本的构建块,因为在这篇关于所有monad的母亲的文章是延续monad.
我想知道是否有适用范围.我的意思是,在continuation monad中包装递归函数或相互递归是否有意义?它有助于提高可读性吗?
这是从这篇SO帖子中获取的延续模式的F#版本:
type ContinuationMonad() =
member this.Bind (m, f) = fun c -> m (fun a -> f a c)
member this.Return x = fun k -> k x
let cont = ContinuationMonad()
Run Code Online (Sandbox Code Playgroud)
仅仅是为了学术兴趣,例如帮助理解monad或计算构建者?或者是否存在一些真实的适用性,增加了类型安全性,还是避免了难以解决的典型编程问题?
即,来自Ryan Riley的call/cc的延续monad表明处理异常很复杂,但它没有解释它试图解决的问题,并且示例没有说明为什么它需要特定的monad.不可否认,我只是不明白它的作用,但它可能是一个宝库!
(注意:我对理解延续monad是如何工作不感兴趣,我认为我对它有一个很好的掌握,我只是看不出它解决了什么编程问题.)
monads f# haskell computation-expression continuation-passing
我正在尝试使用Rx Builder在F#Computation Expression语法中使用Reactive Extension.如何修复它以使它不会破坏堆栈?像下面的Seq示例一样.是否有任何计划提供RxBuilder的实现作为Reactive Extensions的一部分或作为.NET Framework未来版本的一部分?
open System
open System.Linq
open System.Reactive.Linq
type rxBuilder() =
member this.Delay f = Observable.Defer f
member this.Combine (xs: IObservable<_>, ys : IObservable<_>) =
Observable.merge xs ys
member this.Yield x = Observable.Return x
member this.YieldFrom (xs:IObservable<_>) = xs
let rx = rxBuilder()
let rec f x = seq { yield x
yield! f (x + 1) }
let rec g x = rx { yield x
yield! g (x + 1) }
//do f 5 …Run Code Online (Sandbox Code Playgroud) 这是我到目前为止:
type Maybe<'a> = option<'a>
let succeed x = Some(x)
let fail = None
let bind rest p =
match p with
| None -> fail
| Some r -> rest r
let rec whileLoop cond body =
if cond() then
match body() with
| Some() ->
whileLoop cond body
| None ->
fail
else
succeed()
let forLoop (xs : 'T seq) f =
using (xs.GetEnumerator()) (fun it ->
whileLoop
(fun () -> it.MoveNext())
(fun () -> it.Current |> f) …Run Code Online (Sandbox Code Playgroud) 使用以下continuation monad:
type ContinuationMonad() =
member this.Bind (m, f) = fun c -> m (fun a -> f a c)
member this.Return x = fun k -> k x
let cont = ContinuationMonad()
Run Code Online (Sandbox Code Playgroud)
我不明白为什么以下给我一个堆栈溢出:
let map f xs =
let rec map xs =
cont {
match xs with
| [] -> return []
| x :: xs ->
let! xs = map xs
return f x :: xs
}
map xs id;;
let q = [1..100000] |> map ((+) …Run Code Online (Sandbox Code Playgroud) 计算表达式中方法的msdn文档说明了这Zero一点
在计算表达式中调用表达式的空
else分支if...then.
假设我们正在使用一个identity没有Zero定义的计算构建器.
let IdentityBuilder() =
member this.Bind(i, f) = f i
member this.Return(i) = i
let identity = new IdentityBuilder()
Run Code Online (Sandbox Code Playgroud)
允许使用以下代码
identity {
printf "Hello World"
return 1
}
Run Code Online (Sandbox Code Playgroud)
但是,不允许使用以下代码,并且编译器错误会失败
仅当计算表达式构建器定义"零"方法时,才可以使用此控件构造
identity {
if true then printf "Hello World"
return 1
}
Run Code Online (Sandbox Code Playgroud)
为什么编译坚持呼吁Zero为else分支?这背后的直觉是什么?
我有这个名为Desync的monad -
[<AutoOpen>]
module DesyncModule =
/// The Desync monad. Allows the user to define in a sequential style an operation that spans
/// across a bounded number of events. Span is bounded because I've yet to figure out how to
/// make Desync implementation tail-recursive (see note about unbounded recursion in bind). And
/// frankly, I'm not sure if there is a tail-recursive implementation of it...
type [<NoComparison; NoEquality>] Desync<'e, 's, 'a> =
Desync of ('s -> 's * …Run Code Online (Sandbox Code Playgroud) 我试图通过实现我自己的一个来学习更多关于F#的计算表达式.但是,我遇到了与该Bind方法有关的绊脚石.这是我到目前为止所得到的:
type public op<'a> = Op of ('a list -> 'a list)
let inline (>>) (Op a) (Op b) = Op (a >> b)
module Op =
let id = Op id
let bind (b : 'b -> op<'a>) (v : 'b) = b v
let call (Op f) = f
let push v = Op (fun t -> v :: t)
// .. snip ..
type OpBuilder() =
member __.Bind (v, b) = Op.bind b v
member …Run Code Online (Sandbox Code Playgroud) TL; DR:如何在以后引发先前捕获的异常,同时保留原始异常的堆栈跟踪.
因为我认为这对Resultmonad或计算表达式很有用,尤其是 因为该模式通常用于包装异常而不抛出异常,所以这里有一个很好的例子:
type Result<'TResult, 'TError> =
| Success of 'TResult
| Fail of 'TError
module Result =
let bind f =
function
| Success v -> f v
| Fail e -> Fail e
let create v = Success v
let retnFrom v = v
type ResultBuilder () =
member __.Bind (m , f) = bind f m
member __.Return (v) = create v
member __.ReturnFrom (v) = retnFrom v
member __.Delay (f) = f
member …Run Code Online (Sandbox Code Playgroud) 我正在尝试向URL发出异步Web请求,如果请求耗时太长,将返回该URL.我正在使用F#异步工作流和System.Net.Http库来执行此操作.
但是,我无法捕获async工作流中System.Net.Http库引发的Task/OperationCancelledExceptions .相反,异常是在Async.RunSynchronously方法中引发的,如此堆栈跟踪中所示:
> System.OperationCanceledException: The operation was canceled. at
> Microsoft.FSharp.Control.AsyncBuilderImpl.commit[a](Result`1 res)
> at
> Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously[a](CancellationToken
> token, FSharpAsync`1 computation, FSharpOption`1 timeout) at
> Microsoft.FSharp.Control.FSharpAsync.RunSynchronously[T](FSharpAsync`1
> computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken)
> at <StartupCode$FSI_0004>.$FSI_0004.main@()
Run Code Online (Sandbox Code Playgroud)
代码:
#r "System.Net.Http"
open System.Net.Http
open System
let readGoogle () = async {
try
let request = new HttpRequestMessage(HttpMethod.Get, "https://google.co.uk")
let client = new HttpClient()
client.Timeout <- TimeSpan.FromSeconds(0.01) //intentionally low to always fail in this example
let! response = client.SendAsync(request, HttpCompletionOption.ResponseContentRead) |> Async.AwaitTask …Run Code Online (Sandbox Code Playgroud) f# async-workflow task-parallel-library computation-expression
我一直在研究带有 F# 计算表达式的 State Monad,我也在尝试利用自定义操作。我得到了一些没有意义的奇怪行为。编译器报告一个值在上面两行声明时不存在。
type State<'a, 's> = ('s -> 'a * 's)
module State =
// Explicit
// let result x : State<'a, 's> = fun s -> x, s
// Less explicit but works better with other, existing functions:
let result x s =
x, s
let bind (f:'a -> State<'b, 's>) (m:State<'a, 's>) : State<'b, 's> =
// return a function that takes the state
fun s ->
// Get the value and next state from …Run Code Online (Sandbox Code Playgroud)