Haskell composition (.) vs F#'s pipe forward operator (|>)

前端 未结 10 1612
鱼传尺愫
鱼传尺愫 2020-12-04 07:36

In F#, use of the the pipe-forward operator, |>, is pretty common. However, in Haskell I\'ve only ever seen function composition, (.), being us

相关标签:
10条回答
  • 2020-12-04 07:58

    More speculation, this time from the predominantly Haskell side...

    ($) is the flip of (|>), and its use is quite common when you can't write point-free code. So the main reason that (|>) not used in Haskell is that its place is already taken by ($).

    Also, speaking from a bit of F# experience, I think (|>) is so popular in F# code because it resembles the Subject.Verb(Object) structure of OO. Since F# is aiming for a smooth functional/OO integration, Subject |> Verb Object is a pretty smooth transition for new functional programmers.

    Personally, I like thinking left-to-right too, so I use (|>) in Haskell, but I don't think many other people do.

    0 讨论(0)
  • 2020-12-04 08:01

    If you want to use F#'s |> in Haskell then in Data.Function is the & operator (since base 4.8.0.0).

    0 讨论(0)
  • 2020-12-04 08:04

    I think F#'s pipe forward operator (|>) should vs (&) in 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
    

    If you dont like (&) operator, you can custom it like F# or Elixir :

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

    Why infixl 1 |>? See the doc in Data-Function (&)

    infixl = infix + left associativity

    infixr = infix + right associativity


    (.)

    (.) means function composition. It means (f.g)(x) = f(g(x)) in Math.

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

    it equals

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

    or

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

    ($) operator is also defind in Data-Function ($).

    (.) is used for create Hight Order Function or closure in js. See example:

    
    // (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]
    

    Wow, Less (code) is better.


    Compare |> and .

    ghci> 5 |> factorial |> show
    
    // equals
    
    ghci> (show . factorial) 5 
    
    // equals
    
    ghci> show . factorial $ 5 
    

    It is the different between left —> right and right —> left. ⊙﹏⊙|||

    Humanization

    |> and & is better than .

    because

    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
    
    

    How to functional programming in object-oriented language?

    please visit http://reactivex.io/

    It support :

    • Java: RxJava
    • JavaScript: RxJS
    • C#: Rx.NET
    • C#(Unity): UniRx
    • Scala: RxScala
    • Clojure: RxClojure
    • C++: RxCpp
    • Lua: RxLua
    • Ruby: Rx.rb
    • Python: RxPY
    • Go: RxGo
    • Groovy: RxGroovy
    • JRuby: RxJRuby
    • Kotlin: RxKotlin
    • Swift: RxSwift
    • PHP: RxPHP
    • Elixir: reaxive
    • Dart: RxDart
    0 讨论(0)
  • 2020-12-04 08:08

    Aside from style and culture, this boils down to optimizing the language design for either pure or impure code.

    The |> operator is common in F# largely because it helps to hide two limitations that appear with predominantly-impure code:

    • Left-to-right type inference without structural subtypes.
    • The value restriction.

    Note that the former limitation does not exist in OCaml because subtyping is structural instead of nominal, so the structural type is easily refined via unification as type inference progresses.

    Haskell takes a different trade-off, choosing to focus on predominantly-pure code where these limitations can be lifted.

    0 讨论(0)
提交回复
热议问题