当前位置:  开发笔记 > 编程语言 > 正文

Haskell组合(.)与F#的管道前向运算符(|>)

如何解决《Haskell组合(.)与F#的管道前向运算符(|>)》经验,为你挑选了9个好方法。

在F#中,使用管道前向运算符|>非常常见.但是,在Haskell中,我只见过使用过的函数组合(.).我知道它们是相关的,但是有没有一种语言原因在Haskell中没有使用管道转发,还是其他什么?



1> GS - Apologi..:

在F#(|>)中,由于从左到右的类型检查很重要.例如:

List.map (fun x -> x.Value) xs

通常不会进行类型检查,因为即使xs已知类型,在类型检查器x看到lambda 的参数类型时也不知道,因此它不知道如何解决x.Value.

相反

xs |> List.map (fun x -> x.Value)

将工作正常,因为类型xs将导致x被知道的类型.

从左到右的类型检查是必需的,因为在结构中涉及名称解析x.Value.Simon Peyton Jones写了一篇关于为Haskell添加类似名称解析的提议,但他建议使用局部约束来跟踪类型是否支持特定操作.因此,在第一个样本中,x需要Value财产的需求将被推进,直到xs看到并且可以解决此要求.但这确实使类型系统复杂化.


(<|)实际上类似于Haskell($).从左到右的类型检查只需要解析像.Value这样的东西,所以(<|)在其他场景中工作正常,或者如果你使用显式类型注释.

2> Brian..:

我有点投机......

文化:我认为|>是F#"文化"中的重要运营商,也许与.Haskell 类似.F#有一个函数组合运算符,<<但我认为F#社区倾向于使用比Haskell社区更少的无点样式.

语言差异:我对两种语言的比较都知之甚少,但是推广let-bindings的规则可能会有很大的不同,从而影响到这一点.例如,我知道在F#中有时写作

let f = exp

不会编译,你需要明确的eta转换:

let f x = (exp) x   // or x |> exp

使它编译.这也引导人们远离无点/组合风格,并走向流水线风格.此外,F#类型推断有时需要流水线操作,因此左侧会显示已知类型(请参见此处).

(就个人而言,我觉得无点的风格是不可读的,但我认为每一个新的/不同的东西似乎都不可读,直到你习惯了它.)

我认为两种语言都可能存在,历史/文化/事故可能会定义为什么每个社区都选择不同的"吸引者".


无点有时比有点可读更有可读性,有时更少.我通常在map和filter等函数的参数中使用它,以避免lambda混乱.我有时也会在顶级函数中使用它,但不经常使用它,只有当它的内容很简单时才使用它.
我同意文化差异.传统的Haskell使用`.`和`$`,所以人们继续使用它们.
我没有看到太多的文化,因为就F#而言,在这个问题上根本就没有多少选择(因为你和Ganesh提到的原因).所以我要说两者在Haskell中都是可行的,但是F#对于使用管道运算符肯定要好得多.

3> Nathan Shive..:

更多的猜测,这次来自Haskell主导方面......

($)是你的翻版(|>),当你无法编写无点代码时,它的使用非常普遍.因此,(|>)在Haskell 中没有使用的主要原因是它已经占据了它的位置($).

另外,从F#的一些经验来看,我认为(|>)它在F#代码中非常流行,因为它类似于Subject.Verb(Object)OO 的结构.由于F#旨在实现平滑的功能/ OO集成,Subject |> Verb Object因此对于新的功能程序员来说是一个非常平滑的过渡.

就个人而言,我也喜欢从左到右思考,所以我(|>)在Haskell中使用,但我不认为很多其他人会这样做.


在实践中,F#的`|>`实际上让我想起了UNIX` |`而不是其他任何东西.
@mattbh:不是我能找到Hoogle.我不知道`Data.Sequence.|>`,但是`$>`看起来合理,以避免那里的冲突.老实说,只有那么多好看的操作符,所以我只会使用`|>`并根据具体情况管理冲突.(我也很想把`Data.Sequence.|>`别名为`snoc`)
`($)`和`(|>)是应用程序而不是组成。两者是相关的(如问题注释所示),但它们是不相同的(函数的fc是(Control.Arrow。>>>)`)。
F#中的`|>`的另一个好处是,它在Visual Studio中具有IntelliSense的漂亮属性。键入“ |>”,您将获得可以应用于左侧值的函数列表,类似于在对象后键入“。”时发生的情况。

4> AshleyF..:

我认为我们混淆了一些事情.Haskell(.)相当于F#(>>).不要与F#的(|>)只是反转函数应用程序混淆,就像Haskell的($) - 反转:

let (>>) f g x = g (f x)
let (|>) x f = f x

我相信Haskell程序员$经常使用.也许不像F#程序员经常使用的那样频繁|>.另一方面,一些F#家伙使用>>到一个荒谬的程度:http://blogs.msdn.com/b/ashleyf/archive/2011/04/21/programming-is-pointless.aspx


我认为(`.`)和(```)相同,而(`>>`)是反向组合.那就是`(>>):('T1 - >'T2) - >('T2 - >'T3) - >'T1 - >'T3` vs`(<<):('T2 - >'T3) - >('T1 - >'T2) - >'T1 - >'T3`
正如你所说的那样,就像Haskell的`$`运算符 - 反转,你也可以很容易地将它定义为:`a |> b = flip($)`它等同于F#的管道,例如你可以做`[1..10] |> map f`

5> jhegedus..:

如果你想|>在Haskell中使用F#,那么在Data.Function中就是&运算符(自base 4.8.0.0).



6> sastanin..:

Haskell中从左到右的组合

有些人也在Haskell中使用从左到右(消息传递)的方式.见,例如,MPS上Hackage库.一个例子:

euler_1 = ( [3,6..999] ++ [5,10..999] ).unique.sum

我认为这种风格在某些情况下看起来很不错,但它更难阅读(需要知道库及其所有操作符,重新定义(.)也令人不安).

Control.Category中还有从左到右以及从右到左的合成运算符,它们是基础包的一部分.比较>>><<<分别:

ghci> :m + Control.Category
ghci> let f = (+2) ; g = (*3) in map ($1) [f >>> g, f <<< g]
[9,5]

有时候选择从左到右的构图是有充分理由的:评估顺序遵循阅读顺序.



7> spookylukey..:

我已经看到>>>被用于flip (.),我经常使用它,特别是对于从左到右最好理解的长链.

>>> 实际上来自Control.Arrow,并且不仅仅是函数.



8> Jon Harrop..:

除了风格和文化之外,这归结为优化纯语言或不纯代码的语言设计.

|>运营商在F#中常见的主要是因为它有助于隐藏与主要-不纯的代码将出现两个限制:

从左到右的类型推断没有结构子类型.

价值限制.

注意,OCaml中不存在前一个限制,因为子类型是结构而不是名义,因此随着类型推断的进展,结构类型很容易通过统一来细化.

Haskell采取了不同的权衡,选择专注于主要纯粹的代码,可以解除这些限制.



9> lihansey..:

我认为F#的管道前移运算符(|>)应该与haskell中的()对决。

// pipe operator example in haskell

factorial :: (Eq a, Num a) =>  a -> a
factorial x =
  case x of
    1 -> 1
    _ -> x * factorial (x-1)

// terminal
ghic >> 5 & factorial & show

如果您不喜欢(&)运算符,则可以像F#或Elixir一样自定义它:

(|>) :: a -> (a -> b) -> b
(|>) x f = f x
infixl 1 |>
ghci>> 5 |> factorial |> show

为什么infixl 1 |>呢 请参阅数据功能(&)中的文档

infixl =中缀+左联想

infixr =中缀+右关联


(。)

.)表示功能组成。在数学中表示(fg)(x)= f(g(x))。

foo = negate . (*3)
// ouput -3
ghci>> foo 1
// ouput -15
ghci>> foo 5

它等于

// (1)
foo x = negate (x * 3) 

要么

// (2)
foo x = negate $ x * 3 

$)运算符也在Data-Function($)中定义。

.)用于创建Hight Order Functionclosure in js。参见示例:


// (1) use lamda expression to create a Hight Order Function
ghci> map (\x -> negate (abs x)) [5,-3,-6,7,-3,2,-19,24]  
[-5,-3,-6,-7,-3,-2,-19,-24]


// (2) use . operator to create a Hight Order Function
ghci> map (negate . abs) [5,-3,-6,7,-3,2,-19,24]  
[-5,-3,-6,-7,-3,-2,-19,-24]

哇,更少(代码)更好。


比较|>.
ghci> 5 |> factorial |> show

// equals

ghci> (show . factorial) 5 

// equals

ghci> show . factorial $ 5 

left —> right和之间是不同的right —> left。??? |||

人性化

|>并且&.

因为

ghci> sum (replicate 5 (max 6.7 8.9))

// equals

ghci> 8.9 & max 6.7 & replicate 5 & sum

// equals

ghci> 8.9 |> max 6.7 |> replicate 5 |> sum

// equals

ghci> (sum . replicate 5 . max 6.7) 8.9

// equals

ghci> sum . replicate 5 . max 6.7 $ 8.9

如何使用面向对象的语言进行功能编程?

请访问http://reactivex.io/

IT支持 :

Java:RxJava

JavaScript:RxJS

C#:Rx.NET

C#(统一):UniRx

Scala:RxScala

Clojure:RxClojure

C ++:RxCpp

Lua:RxLua

Ruby:Rx.rb

Python:RxPY

转到:RxGo

Groovy:RxGroovy

JRuby:RxJRuby

Kotlin:RxKotlin

斯威夫特:RxSwift

PHP:RxPHP

长生不老药

飞镖:RxDart

推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有