Fil*_*und 0 typeclass do-notation purescript
我可以像这样替换 do-block 吗:
do
...
pure ...
Run Code Online (Sandbox Code Playgroud)
其中最后一行是“纯粹”的东西,带有这样的 ado 块:
ado
...
in ...
Run Code Online (Sandbox Code Playgroud)
?
我知道do只需要Bind而不是Monad(即Applicative),但我们已经在使用pure,所以我们已经Applicative。
adoApplicative(以及因此的 applicative do - )和 Monad ( bindor )之间的区别do在于,当组合两个应用计算时,第二个计算不能依赖于第一个计算的结果。这意味着:
do
x <- getX
y <- getY
pure { x, y }
-- Can be turned into
ado
x <- getX
y <- getY
in { x, y }
Run Code Online (Sandbox Code Playgroud)
但如果 y 取决于 x 我们就不能这样做:
do
x <- getX
y <- getY x
pure { x, y }
-- This won't compile
ado
x <- getX
y <- getY x
in { x, y }
Run Code Online (Sandbox Code Playgroud)
这意味着您的问题的答案是“否”。
让我们考虑一个直观的例子。Aff Monad 允许我们运行异步效果,例如从 API 获取数据。如果请求是独立的,我们可以并行运行它们。
ado
user1 <- get "/user/1"
user2 <- get "/user/2"
in [user1, user2]
Run Code Online (Sandbox Code Playgroud)
如果它们相互依赖,我们需要一个又一个地运行请求:
do
user1 <- get "/user/1"
bestFriend <- get ("/user/" <> user1.bestFriendId)
pure { user1, bestFriend }
Run Code Online (Sandbox Code Playgroud)
请注意,Aff无论您是否使用bindor apply,它总是按顺序运行,除非我们使用parallelwhich 将 an 转换Aff为 a ParAff。请注意,缺少 Bind/Monad 实例,ParAff因为两个并行计算不能依赖彼此的结果!https://pursuit.purescript.org/packages/purescript-aff/7.1.0/docs/Effect.Aff#t:ParAff
这意味着第一个示例要真正并行运行,我们实际上必须
ado
user1 <- parallel $ get "/user/1"
user2 <- parallel $ get "/user/2"
in [user1, user2]
Run Code Online (Sandbox Code Playgroud)
我喜欢的另一个例子是解析/验证。想象一下您正在解析用户输入的两个字段:日期字符串和年龄。我们可以并行检查这两个属性,如果这两个属性都无效,则返回两个错误。但要验证日期,我们可能首先必须检查输入值是否是字符串,然后检查该值是否是日期字符串。有关示例库,请查看purescript-foreign
validated = ado
date <- do
str <- isString dateInput
isDate date
age <- do
int <- isInt ageInput
isPositive int
in { date, age }
Run Code Online (Sandbox Code Playgroud)
我们看到Applicative比Monad弱很多。但在某些情况下,放弃 Monad 的力量可以给我们带来其他有趣的可能性,例如并行化或多个错误。
| 归档时间: |
|
| 查看次数: |
109 次 |
| 最近记录: |