2

我正在使用一种名为“elm”的语言,它试图将 Haskel-esque 语法和 FRP 引入 Javascript。这里有一些关于从 F# 实现管道运算符的讨论,但语言设计者担心与更标准的(至少在其他 FP 语言中)反向管道运算符相比会增加成本(我假设会增加编译时间或编译器实现复杂性) (榆树已经实现)。任何人都可以谈论这个吗?[也请随意直接发布到该线程,否则如果没有其他人这样做,我将粘贴回最佳答案]。

https://groups.google.com/forum/?fromgroups=#!topic/elm-discuss/Kt0MbDyRpO4

谢谢!

4

3 回答 3

7

在您引用的讨论中,我看到埃文提出了两个挑战:

  1. 给我看一些使用它的 F# 项目
  2. 找一些可靠的 F# 程序员谈论为什么它是一个好主意以及随之而来的成本(博客文章或其他内容)。

我会回答如下:

  1. 正向管道成语在 F# 编程中非常常见,出于文体(我们喜欢它)和实用(它有助于类型推断)的原因。几乎所有你会发现的 F# 项目都会经常使用它。当然,我所有的开源项目都使用它(Unquote,FsEye,NL found here)。毫无疑问,您会发现所有位于 Github 的 F# 项目都相同,包括 F# 编译器源代码本身。

  2. Brian 是 Microsoft F# 编译器团队的一名开发人员,早在 2008 年就发表了一篇关于F# 中的流水线的博客,这是一篇仍然非常有趣且相关的博客,它将 F# 管道与 POSIX 管道联系起来。在我自己的估计中,实施管道操作员的成本非常低。在 F# 编译器中,这在任何意义上都是正确的(它是一个单行的内联函数定义)。

于 2013-02-04T00:06:25.277 回答
3

管道运算符实际上非常简单 - 这是标准定义

let inline (|>) a b = b a

此外,.线程中讨论的运算符是 F# ( ) 中的反向管道运算符,<|它使您能够消除一些括号。

我认为添加管道运营商不会对复杂性产生重大影响

于 2013-02-03T23:58:06.913 回答
2

除了这里已经给出的优秀答案之外,我还想补充几点。

首先,管道运算符在 F# 中很常见的原因之一是它有助于规避当前完成类型推断的方式的缺点。具体来说,如果将聚合操作与使用 OOP 的 lambda 函数应用到集合类型推断通常会失败。例如:

Seq.map (fun z -> z.Real) zs

这会失败,因为 F# 还不知道z遇到该属性时的类型,Real因此它拒绝编译此代码。惯用的解决方法是使用管道运算符:

xs |> Seq.map (fun z -> z.Real)

这非常丑陋(IMO),但它确实有效。

其次,F# 管道运算符在一定程度上很好,但您目前无法获得中间结果的推断类型。例如:

x
|> h
|> g
|> f

如果此时出现类型错误,f程序员将想知道输入的值的类型,f以防问题实际上出在hg但目前在 Visual Studio 中是不可能的。具有讽刺意味的是,这在 OCaml 中使用 Emacs 的 Tuareg 模式很容易,因为您可以获得任何子表达式的推断类型,而不仅仅是标识符。

于 2013-02-04T14:46:28.677 回答