F# 的 monad 实现在可用关键字数量方面是否独特?

发布于 2024-11-07 03:00:33 字数 190 浏览 2 评论 0原文

我只知道F#。我还没有学过其他的函数式编程语言。我见过的所有关于 monad 的例子都只描述了 bind 和 unit 方法。 F# 有很多关键字(例如 let!do! 等),允许您在同一计算表达式中执行不同的操作。这似乎为您提供了比基本绑定和单位方法更多的功能。这是 F# 独有的还是在函数式编程语言中很常见?

I only know F#. I haven't learned the other functional programming languages. All the examples that I have seen for monads only describe the bind and unit methods. F# has lots of keywords (e.g. let!, do!, etc.) that allow you to do different things within the same computational expression. This seemingly gives you more power than your basic bind and unit methods. Is this unique to F# or is it common across functional programming languages?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

白衬杉格子梦 2024-11-14 03:00:34

Monad 是根据 bindunit 操作(仅)来定义的。还有其他由其他操作定义的结构(例如,在 Haskell 中,MonadPlus 类型类具有 zeroplus 操作 - 这些对应于 Zero 和F# 计算表达式中的Combine)。据我所知,F# 的计算构建器在为它们支持的各种操作提供良好的语法方面是独一无二的,但大多数操作与 monad 无关。

Monads are defined in terms of bind and unit operations (only). There are other structures which are defined by other operations (e.g. in Haskell, the MonadPlus typeclass has zero and plus operations - these correspond to Zero and Combine in F# computation expressions). As far as I know, F#'s computation builders are unique in terms of providing nice syntax for the wide range of operations that they support, but most of the operations are unrelated to monads.

意中人 2024-11-14 03:00:34

! 结尾的 F# 绑定形式表示计算表达式,包括 let!使用!做!屈服!返回!

let! pat = expr in comp-expr         -- binding computation

do!  expr in comp-expr               -- sequential computation

use! pat = expr in comp-expr         -- auto cleanup computation

yield! expr                          -- yield computation

return! expr                         -- return computation

计算表达式用于“F# 表达式语法的序列和其他非标准解释”。这些语法形式提供了重载该语法的方法,例如,对一元计算或幺半群计算进行编码,并且看起来类似于 Haskell 的 do-notation 以及相应的(非魔法)该语言的绑定形式。

所以我想说,它们支持某种语法重载,以支持该语言的表达式语法的其他解释,这与许多语言(包括 Haskell 和 OCaml)都有共同点。这无疑是一个强大且有用的语言功能。


参考文献:F# 2.0 语言规范

F# binding forms ending in ! denote computation expressions, including let! use! do! yield! return!.

let! pat = expr in comp-expr         -- binding computation

do!  expr in comp-expr               -- sequential computation

use! pat = expr in comp-expr         -- auto cleanup computation

yield! expr                          -- yield computation

return! expr                         -- return computation

Computation expressions are used "for sequences and other non-standard interpretations of the F# expression syntax". These syntax forms offer ways to overload that syntax, for example, to encode monadic computations, or monoidal computations, and appear to be similar to e.g. the do-notation of Haskell, and corresponding (non-magic) bindings forms in that language.

So I would say that they support some overloading of syntax to support other interpretations of the expression syntax of the language, and this they have in common with many languages, including Haskell and OCaml. It is certainly a powerful and useful language feature.


References: The F# 2.0 Language Specification.

鹿童谣 2024-11-14 03:00:34

(凭记忆回忆一下,我可能跑题了。)

虽然我认为 unitbind 是 monad 的典型基础,但我认为也许 mapjoin 以获得我在学术论文中看到的不同基础。这有点像 LINQ 在 C# 和 VB 中的工作方式,其中各种 from 语法脱糖为 SelectSelectMany ,类似于 地图加入。 LINQ 还有一些“额外”关键字,有点像 F#,但更临时(并且最适合查询枚举/数据库)。

我暂时不知道像 F# 这样的其他函数式语言可以有效地将大部分控制流和其他语法“提升”到 monad 中(好吧,“计算表达式”,可能是也可能不是 monad)。

(Recall from memory, I may be off.)

While I think unit and bind are the typical basis for monads, I think maybe map and join for a different basis that I've seen in academic papers. This is kinda like how LINQ works in C# and VB, where the various from syntax desugars into Select or SelectMany which are similar to map and join. LINQ also has some 'extra' keywords, a little like F# though more ad-hoc (and mostly suited to querying enumerations/databases).

I don't know offhand of other functional languages like F# that effectively "lift" most of the control flow and other syntax into monads (well, "computation expressions", which may or may not be monads).

青衫负雪 2024-11-14 03:00:33

是的,我认为计算表达式的 F# 语法是独特的,因为它为不同类型的计算提供直接语法支持。它可用于处理 monoids、常见的 monad 以及来自 Haskell 的 MonadPlus 计算。

我在我的硕士论文的简介中写了这些内容。我认为这是一个很好读的部分,所以你可以到第27页来阅读。无论如何,我将在这里复制示例:

Monoid 仅用于使用某些“+”操作(Combine)连接值。例如,您可以使用它来构建字符串(这是低效的,但它演示了这个想法):

type StringMonoid() =
  member x.Combine(s1, s2) = String.Concat(s1, s2)
  member x.Zero() = ""
  member x.Yield(s) = s

let str = new StringMonoid()

let hello = str { yield "Hello "
                  yield "world!" };;

Monad 是使用 bindreturn 的熟悉示例em> 计算表达式的运算。例如,也许 monad 表示在任何时候都可能失败的计算:

type MaybeMonad() =
  member x.Bind(m, f) =
    match m with Some(v) -> f v | None -> None
  member x.Return(v) = Some(v)

let maybe = new MaybeMonad()

let rec productNameByID() = maybe {
  let! id = tryReadNumber()
  let! prod = db.TryFindProduct(id)
  return prod.Name }

Additive monads(在 Haskell 中又名 MonadPlus)是两者的组合。它有点像可以产生多个值的一元计算。一个常见的例子是列表(或序列),它可以实现绑定组合

type ListMonadPlus() =
  member x.Zero() = []
  member x.Yield(v) = [v]
  member x.Combine(a, b) = a @ b
  member x.Bind(l, f) = l |> List.map f |> List.concat

let list = new ListMonadPlus()

let cities = list {
  yield "York"
  yield "Orleans" }
let moreCities = list {
  let! n = cities
  yield n
  yield "New " + n }

// Creates: [ "York"; "New York"; "Orleans"; "New Orleans" ]

还有一些额外的功能不直接对应于任何理论思想的关键词。 use 关键字处理资源,forwhile 可用于实现循环。序列/列表理解实际上使用 for 而不是 let!,因为从语法的角度来看,这更有意义(并且 for 通常需要一些顺序 - 尽管它可能是异步的)。

Yes, I think that the F# syntax for computation expressions is unique in that it provides direct syntactic support for different types of computations. It can be used for working with monoids, usual monads and also MonadPlus computations from Haskell.

I wrote about these in the introduction of my Master thesis. I believe it is quite readable part, so you can go to page 27 to read it. Anyway, I'll copy the examples here:

Monoid is used just for concatenating values using some "+" operation (Combine). You can use it for example for building strings (this is inefficient, but it demonstrates the idea):

type StringMonoid() =
  member x.Combine(s1, s2) = String.Concat(s1, s2)
  member x.Zero() = ""
  member x.Yield(s) = s

let str = new StringMonoid()

let hello = str { yield "Hello "
                  yield "world!" };;

Monads are the familiar example that uses bind and return operations of comptuation expressions. For example maybe monad represents computations that can fail at any point:

type MaybeMonad() =
  member x.Bind(m, f) =
    match m with Some(v) -> f v | None -> None
  member x.Return(v) = Some(v)

let maybe = new MaybeMonad()

let rec productNameByID() = maybe {
  let! id = tryReadNumber()
  let! prod = db.TryFindProduct(id)
  return prod.Name }

Additive monads (aka MonadPlus in Haskell) is a combination of the two. It is a bit like monadic computation that can produce multiple values. A common example is list (or sequence), which can implement both bind and combine:

type ListMonadPlus() =
  member x.Zero() = []
  member x.Yield(v) = [v]
  member x.Combine(a, b) = a @ b
  member x.Bind(l, f) = l |> List.map f |> List.concat

let list = new ListMonadPlus()

let cities = list {
  yield "York"
  yield "Orleans" }
let moreCities = list {
  let! n = cities
  yield n
  yield "New " + n }

// Creates: [ "York"; "New York"; "Orleans"; "New Orleans" ]

There are some additional keywords that do not directly correspond to any theoretical idea. The use keyword deals with resources and for and while can be used to implement looping. The sequence/list comprehension actually use for instead of let!, because that makes much more sense from the syntactic point of view (and for usually takes some sequence - although it may be e.g. asynchronous).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文