Jawaban:
Saya menjadi sedikit spekulatif ...
Budaya : Saya pikir |>
adalah operator penting dalam "budaya" F #, dan mungkin serupa dengan .
Haskell. F # memiliki operator komposisi fungsi <<
tetapi menurut saya komunitas F # cenderung menggunakan gaya bebas poin lebih sedikit daripada komunitas Haskell.
Perbedaan bahasa : Saya tidak cukup tahu tentang kedua bahasa untuk dibandingkan, tetapi mungkin aturan untuk menggeneralisasi let-binding cukup berbeda untuk memengaruhi hal ini. Misalnya, saya tahu di F # kadang-kadang menulis
let f = exp
tidak akan dikompilasi, dan Anda memerlukan konversi eta eksplisit:
let f x = (exp) x // or x |> exp
untuk membuatnya dikompilasi. Ini juga menjauhkan orang dari gaya bebas poin / komposisi, dan menuju gaya pipelining. Juga, inferensi tipe F # terkadang menuntut pipelining, sehingga tipe yang diketahui muncul di sebelah kiri (lihat di sini ).
(Secara pribadi, saya menemukan gaya bebas poin tidak dapat dibaca, tetapi saya kira setiap hal baru / berbeda tampaknya tidak dapat dibaca sampai Anda terbiasa.)
Saya pikir keduanya berpotensi layak dalam kedua bahasa, dan sejarah / budaya / kecelakaan dapat menentukan mengapa setiap komunitas menetap di "penarik" yang berbeda.
.
dan $
, jadi orang terus menggunakannya.
Di F # (|>)
penting karena pemeriksaan ketik kiri-ke-kanan. Sebagai contoh:
List.map (fun x -> x.Value) xs
umumnya tidak akan memeriksa kesalahan ketik, karena meskipun jenisnya xs
diketahui, jenis argumen x
ke lambda tidak diketahui pada saat pemeriksa ketik melihatnya, jadi tidak tahu bagaimana menyelesaikannya x.Value
.
Sebaliknya
xs |> List.map (fun x -> x.Value)
akan berfungsi dengan baik, karena jenis xs
akan mengarah pada jenis x
yang diketahui.
Pemeriksaan ketik kiri-ke-kanan diperlukan karena resolusi nama yang terlibat dalam konstruksi seperti x.Value
. Simon Peyton Jones telah menulis proposal untuk menambahkan jenis resolusi nama yang serupa ke Haskell, tetapi ia menyarankan menggunakan batasan lokal untuk melacak apakah suatu jenis mendukung operasi tertentu atau tidak. Jadi dalam sampel pertama persyaratan yang x
membutuhkan Value
properti akan diteruskan sampai xs
terlihat dan persyaratan ini dapat diselesaikan. Ini memang memperumit sistem tipe.
Lebih banyak spekulasi, kali ini dari sisi yang didominasi Haskell ...
($)
adalah kebalikan dari (|>)
, dan penggunaannya cukup umum ketika Anda tidak dapat menulis kode tanpa poin. Jadi alasan utama yang (|>)
tidak digunakan di Haskell adalah karena tempatnya sudah diambil alih ($)
.
Juga, berbicara dari sedikit pengalaman F #, saya pikir (|>)
sangat populer di kode F # karena menyerupai Subject.Verb(Object)
struktur OO. Karena F # bertujuan untuk integrasi fungsional / OO yang mulus, Subject |> Verb Object
merupakan transisi yang cukup mulus untuk programmer fungsional baru.
Secara pribadi, saya juga suka berpikir dari kiri ke kanan, jadi saya menggunakan (|>)
di Haskell, tapi menurut saya tidak banyak orang yang melakukannya.
Data.Sequence.|>
, tetapi $>
terlihat masuk akal untuk menghindari konflik di sana. Sejujurnya, hanya ada begitu banyak operator yang tampan, jadi saya hanya akan menggunakan |>
keduanya dan mengelola konflik berdasarkan kasus per kasus. (Juga saya akan tergoda untuk hanya alias Data.Sequence.|>
sebagai snoc
)
($)
dan (|>)
apakah aplikasi bukan komposisi. Keduanya berhubungan (sebagai catatan pertanyaan) tetapi mereka tidak sama (Anda fc
adalah (Control.Arrow.>>>)
untuk fungsi).
|>
sebenarnya mengingatkan saya pada UNIX |
lebih dari apapun.
|>
di F # adalah memiliki properti yang bagus untuk IntelliSense di Visual Studio. Ketik |>
, dan Anda mendapatkan daftar fungsi yang dapat diterapkan ke nilai di sebelah kiri, mirip dengan apa yang terjadi saat mengetik .
setelah objek.
Saya pikir kami sedang membingungkan. Haskell's ( .
) setara dengan F #'s ( >>
). Jangan bingung dengan F # 's ( |>
) yang hanya aplikasi fungsi terbalik dan seperti Haskell's ( $
) - terbalik:
let (>>) f g x = g (f x)
let (|>) x f = f x
Saya yakin programmer Haskell memang $
sering menggunakannya . Mungkin tidak sesering pemrogram F # cenderung menggunakan |>
. Di sisi lain, beberapa orang F # menggunakan >>
gelar yang konyol: http://blogs.msdn.com/b/ashleyf/archive/2011/04/21/programming-is-pointless.aspx
$
operator Haskell - terbalik, Anda juga dapat dengan mudah mendefinisikannya sebagai: a |> b = flip ($)
yang setara dengan pipeline F #, misalnya Anda dapat melakukannya[1..10] |> map f
.
) sama dengan ( <<
), sedangkan ( >>
) adalah komposisi kebalikannya. Yaitu ( >> ) : ('T1 -> 'T2) -> ('T2 -> 'T3) -> 'T1 -> 'T3
vs( << ) : ('T2 -> 'T3) -> ('T1 -> 'T2) -> 'T1 -> 'T3
.
sama dengan >>
. Saya tidak tahu apakah F # memiliki <<
tetapi itu akan menjadi setara (seperti di Elm).
Jika Anda ingin menggunakan F # |>
di Haskell maka di Data.Function adalah &
operatornya (sejak base 4.8.0.0
).
&
lebih |>
? Saya merasa |>
jauh lebih intuitif, dan itu juga mengingatkan saya pada operator pipa Unix.
Beberapa orang menggunakan gaya kiri-ke-kanan (penyampaian pesan) di Haskell juga. Lihat, misalnya, pustaka mps di Hackage. Sebuah contoh:
euler_1 = ( [3,6..999] ++ [5,10..999] ).unique.sum
Saya pikir gaya ini terlihat bagus dalam beberapa situasi, tetapi lebih sulit untuk dibaca (seseorang perlu mengetahui perpustakaan dan semua operatornya, definisi ulang (.)
juga mengganggu).
Ada juga operator komposisi kiri-ke-kanan serta kanan-ke-kiri di Control.Category , bagian dari paket dasar. Bandingkan >>>
dan <<<
masing - masing:
ghci> :m + Control.Category
ghci> let f = (+2) ; g = (*3) in map ($1) [f >>> g, f <<< g]
[9,5]
Terkadang ada alasan bagus untuk memilih komposisi kiri-ke-kanan: urutan evaluasi mengikuti urutan pembacaan.
Saya telah melihat >>>
digunakan untuk flip (.)
, dan saya sering menggunakannya sendiri, terutama untuk rantai panjang yang paling baik dipahami dari kiri-ke-kanan.
>>>
sebenarnya dari Control.Arrow, dan bekerja pada lebih dari sekadar fungsi.
>>>
didefinisikan dalam Control.Category
.
Selain gaya dan budaya, ini bermuara pada pengoptimalan desain bahasa untuk kode murni atau tidak murni.
The |>
operator adalah umum di F # sebagian besar karena membantu menyembunyikan dua keterbatasan yang muncul dengan kode dominan-tidak murni:
Perhatikan bahwa batasan sebelumnya tidak ada di OCaml karena subtipe bersifat struktural, bukan nominal, sehingga tipe struktural mudah disempurnakan melalui penyatuan saat inferensi tipe berlangsung.
Haskell mengambil trade-off yang berbeda, memilih untuk fokus pada kode yang didominasi murni di mana batasan ini dapat dicabut.
Saya pikir operator pipa forward F # ( |>
) harus vs ( & ) di 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
Jika Anda tidak menyukai &
operator ( ), Anda dapat menyesuaikannya seperti F # atau Elixir:
(|>) :: a -> (a -> b) -> b
(|>) x f = f x
infixl 1 |>
ghci>> 5 |> factorial |> show
Kenapa infixl 1 |>
? Lihat dokumen di Data-Function (&)
infixl = infix + asosiatif kiri
infixr = infix + asosiatif kanan
( .
) berarti komposisi fungsi. Artinya (fg) (x) = f (g (x)) dalam Matematika.
foo = negate . (*3)
// ouput -3
ghci>> foo 1
// ouput -15
ghci>> foo 5
itu sama
// (1)
foo x = negate (x * 3)
atau
// (2)
foo x = negate $ x * 3
Operator ( $
) juga didefinisikan dalam Data-Function ($) .
( .
) digunakan untuk membuat Hight Order Function
atau closure in js
. Lihat contoh:
// (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, Lebih sedikit (kode) lebih baik.
|>
dan.
ghci> 5 |> factorial |> show
// equals
ghci> (show . factorial) 5
// equals
ghci> show . factorial $ 5
Ini adalah perbedaan antara left —> right
dan right —> left
. ⊙﹏⊙ ||i>
|>
dan &
lebih baik dari.
karena
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
silakan kunjungi http://reactivex.io/
Ini mendukung:
Ini adalah hari pertama saya mencoba Haskell (setelah Rust dan F #), dan saya bisa mendefinisikan operator F #'s |>:
(|>) :: a -> (a -> b) -> b
(|>) x f = f x
infixl 0 |>
dan sepertinya berhasil:
factorial x =
case x of
1 -> 1
_ -> x * factorial (x-1)
main =
5 |> factorial |> print
Saya yakin pakar Haskell dapat memberi Anda solusi yang lebih baik.
x |> f = f x
&
adalah milik Haskell|>
. Terkubur jauh di dalam utas ini dan butuh beberapa hari untuk saya temukan. Saya sering menggunakannya, karena Anda biasanya membaca dari kiri ke kanan untuk mengikuti kode Anda.