- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我看到的典型 Pause monad 实现如下所示(基于 Giulia Costantini 和 Giuseppe Maggiore 编写的 Friendly F# 的第 5 章)。
open System
type Process<'a> = unit -> 'a Step
and Step<'a> =
| Continue of 'a
| Paused of 'a Process
type PauseMonad () =
member this.Return x = fun () -> Continue x
member this.ReturnFrom x = x
member this.Bind (result, rest) =
fun () ->
match result () with
| Continue x -> rest x ()
| Paused p -> Paused (this.Bind (p, rest))
let yield_ () =
fun () ->
Paused (fun () ->
Continue ())
let get_process_step process_ step = do printfn "Process %d, step %d." process_ step
let get_last_process_step process_ = do printfn "Process %d finished." process_
let rec get_process process_ step_count =
PauseMonad () {
do! yield_ ()
if step_count = 0 then
do get_last_process_step process_
return ()
else
do get_process_step process_ step_count
return! get_process process_ <| step_count - 1
}
let rec race p1 p2 =
match p1 (), p2 () with
| Continue _, _ -> do printfn "Process 1 finished first."
| _, Continue _ -> do printfn "Process 2 finished first."
| Paused p1_, Paused p2_ -> race (p1_) (p2_)
[<EntryPoint>]
let main _ =
let process_1 = get_process 1 5
let process_2 = get_process 2 7
do race process_1 process_2
0
Here是 Haskell 中的类似实现。
但是,摆脱相互递归类型 Process 和 Step 并仅使用单个递归类型 Process 似乎更简单,如下所示。
open System
type Process<'a> =
| Continue of 'a
| Paused of (unit -> 'a Process)
type PauseMonad () =
member this.Return x = Continue x
member this.ReturnFrom x = x
member this.Bind (result, rest) =
match result with
| Continue x -> Paused (fun () -> rest x)
| Paused p -> Paused (fun () -> this.Bind (p (), rest))
let yield_ () =
Paused (fun () ->
Continue ())
let get_process_step process_ step = do printfn "Process %d, step %d." process_ step
let get_last_process_step process_ = do printfn "Process %d finished." process_
let rec get_process process_ step_count =
PauseMonad () {
do! yield_ ()
if step_count = 0 then
do get_last_process_step process_
return ()
else
do get_process_step process_ step_count
return! get_process process_ <| step_count - 1
}
let rec race p1 p2 =
match p1, p2 with
| Continue _, _ -> do printfn "Process 1 finished first."
| _, Continue _ -> do printfn "Process 2 finished first."
| Paused p1_, Paused p2_ -> race (p1_ ()) (p2_ ())
[<EntryPoint>]
let main _ =
let process_1 = get_process 1 5
let process_2 = get_process 2 7
do race process_1 process_2
0
这些实现中的任何一个都会给我相同的输出:
Process 1, step 5.
Process 2, step 7.
Process 1, step 4.
Process 2, step 6.
Process 1, step 3.
Process 2, step 5.
Process 1, step 2.
Process 2, step 4.
Process 1, step 1.
Process 2, step 3.
Process 1 finished.
Process 2, step 2.
Process 1 finished first.
我已使这两个实现尽可能相似,以便于区分。据我所知,唯一的区别是:
在第一个版本中,yield_、PauseMonad.Return 和 PauseMonad.Bind 为返回值添加了延迟。在第二个版本中,PauseMonad.Return 在 Paused 包装器中添加了延迟。
在第一个版本中,PauseMonad.Bind 运行结果过程的一个步骤,以查看返回值是否匹配 Continue 或 Paused。在第二个版本中,PauseMonad.Bind只有在确定匹配Paused后才运行结果过程的一步。
在第一个版本中,race 运行每个进程的一个步骤,检查两个结果是否与 Paused 匹配,然后对其余进程进行递归。在第二个版本中,race 检查两个进程是否匹配 Paused,然后运行每个进程的一个步骤,并使用这些步骤的返回值进行递归。
第一个版本更好的原因是什么?
最佳答案
将代码从 Haskell 转换为 F# 有点棘手,因为 Haskell 是惰性的,所以无论何时看到任何值,都说 'a
在 Haskell 中,您可以将其解释为 unit -> 'a
(或更准确地说,作为 Lazy<'a>
)- 所以一切都被隐式延迟。
但是让我们比较一下 F# 中的两个定义:
// Process is always delayed
type Process1<'a> = unit -> 'a Step1
and Step1<'a> = Continue1 of 'a | Paused1 of 'a Process1
// Process is a value or a delayed computation
type Process2<'a> = Continue2 of 'a | Paused2 of (unit -> 'a Process2)
关键区别在于,当您想要表示立即产生值的计算时,在第一种情况下这必须是一个完全评估的值,但在第二种情况下它可以是一个执行某些操作并返回一个值的函数案子。例如:
let primitive1 : Process1<int> = fun () ->
printfn "hi!" // This will print when the computation is evaluated
Continue1(42) )
let primitive2 : Process2<int> =
printfn "hi!" // This will print immediately and returns a monadic value
Continue2(42)
当您添加 Delay
时,这会变得很有趣计算的成员,它可以让你编写类似下面的东西而不评估副作用:
process {
printfn "Hi" // Using Process1, we can easily delay this
// Using Process2, this is trickier (or we run it immediately)
return 42 }
对此有很多话要说,您可以找到更多信息in a recent article I wrote about computation expressions .
关于f# - Pause Monad - monadic 类型应该是什么样的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28079079/
monad 被定义为类别 C 上的内仿函数。假设 C 具有类型 int 和 bool 以及其他构造类型作为对象。现在让我们考虑在这个类别上定义的列表 monad。 根据它的定义,list 是一个内仿函
我试图采取例如ExceptT a (StateT A M) , 对于某些具体类型 A和单子(monad)M ,并将它们包装到我的新自定义单子(monad)中。 首先我确定StateT A M经常出现在
我读到(例如 here 和 here )所有基本单子(monad)(Mabye, Error, ...) 源自其相应的 monad 转换器(MaybeT, ErrorT, ...) 使用身份 mona
Haskell 的状态单子(monad) State s a迫使我保持相同类型的 s在整个做 block 期间。但是由于 state monad 实际上只是一个函数,如果我将它定义为 State
我一直在阅读some materials on free monads而且我真的不认为我离实现更近了,但我认为我更接近于理解它们是什么! 鉴于上述大量资源,我的理解是自由单子(monad)从“计算”工
假设我有一个由两个 monad 操作组成的函数: co::Monad m => m a -> m a -> m a 您可以将 co 视为一个高阶函数,它描述两个单子(monad)操作如何相互协作来完成
在 SO解释了为什么像 scalaz、cats (Scala) 或 Arrow (Kotlin) 中的 Validation 不能是 monad。 据我所知,这是因为他们已经根据应用仿函数对 mona
我对 Haskell 还很陌生,并且慢慢地意识到 Monad fail 的存在有问题。真实世界的 Haskell warns against its use (“再一次,我们建议您几乎总是避免使用失败
我正在阅读现实世界 Haskell 中的 monad 转换器。在以下示例中,堆栈为 Writer在顶部State在Reader之上在IO之上。 {-# Language GeneralizedNewt
我看到的典型 Pause monad 实现如下所示(基于 Giulia Costantini 和 Giuseppe Maggiore 编写的 Friendly F# 的第 5 章)。 open Sys
“Monads 允许程序员使用顺序构建 block 来构建计算”,因此它允许我们组合一些计算。如果是这样,那为什么下面的代码不能运行呢? import Control.Monad.Trans.Stat
这是我第一次认识 Monad Transformers,所以答案可能很明显。 假设我在 StateT MyMonad MyType 类型的 do 块中,我想让另一个相同类型的函数修改状态并返回 MyM
人们通常说类型是单子(monad)。 在某些函数式语言和库(如 Scala/Scalaz)中,您有一个类型构造函数,如 List 或 Option,您可以定义一个与原始类型分离的 Monad 实现。所
我的目标是创建一个函数,该函数在 ReaderT WriterT 堆栈或 RWS 堆栈中使用 list monad。更一般地说,我如何在 mtl 类型类(如 MonadReader、MonadWrit
我只是想知道是否有一个简洁的术语来表示既是单子(monad)又是单子(monad)的东西。我做了一些搜索,我知道these structures exist ,但我还没有找到他们的名字。 最佳答案 在
我正在玩写一个网络应用程序。在这种情况下,我使用 scotty和 redis ,但是这个问题出现在任何 web/db 组合中。在此之前我使用了 happstack,所以我也喜欢那里的一个例子。 Sco
是 x >>= f相当于 retract (liftF x >>= liftF . f) ? 也就是说,从同样是 Monad 的 Functor 构建的自由 monad 的 monad 实例是否将具有
我正在尝试编写一个只能包含 Num 的新 monad。当它失败时,它返回 0,就像 Maybe monad 在失败时返回 Nothing 一样。 这是我到目前为止所拥有的: data (Num a)
我正在使用 operational monad作者:海因里希·阿普菲尔姆斯。 我想用结果类型的 monad 参数化解释器。 我的代码的以下版本编译: {-# LANGUAGE GADTs #-} im
假设所有的 monad 都可以用 Free 来表示。 (如果这不是真的,什么是反例,为什么)?怎么可能the continuation monad或其对应的变压器用 Free 表示或 FreeT -
我是一名优秀的程序员,十分优秀!