Відповіді:
Я трохи роздумую ...
Культура : Я думаю |>, що це важливий оператор у F # "культурі", а можливо, аналогічно з .Haskell. F # має оператор композиції функцій, <<але я думаю, що спільнота F # має тенденцію використовувати стиль без точок менше, ніж у спільноти Haskell.
Мовні відмінності : я не знаю достатньо обох мов для порівняння, але, можливо, правила узагальнення прив’язок є досить різними, щоб вплинути на це. Наприклад, я знаю, що в F # іноді пишу
let f = exp
не компілюється, і вам потрібна явна ета-конверсія:
let f x = (exp) x // or x |> exp
змусити його складати. Це також відволікає людей від стилю, що не належить до очок / композиції, та до конвеєрного стилю. Також висновок типу F # іноді вимагає конвеєрного руху, так що відомий тип з’являється зліва (див. Тут ).
(Особисто я вважаю, що стиль без очок не читається, але я вважаю, що кожна нова / інша річ здається нечитабельною, поки ти не звикнеш до неї.)
Я думаю, що обидва є потенційно життєздатними на будь-якій мові, і історія / культура / нещасний випадок може визначити, чому кожна громада оселилася на різному «притягувачі».
.і $, тому люди продовжують їх використовувати.
У F # (|>)важливо через перевірку типу "зліва направо". Наприклад:
List.map (fun x -> x.Value) xs
як правило, не буде перевірено набір тексту, оскільки навіть якщо тип xsвідомий, тип аргументу xлямбда не відомий у той момент, коли його перевіряє, тому він не знає, як вирішити x.Value.
У контрасті
xs |> List.map (fun x -> x.Value)
буде добре працювати, тому що тип xsводіння призведе до типу xвідомого.
Перевірка типу вліво-вправо потрібна через роздільну здатність імен, що беруть участь у таких конструкціях x.Value. Саймон Пейтон Джонс написав пропозицію щодо додавання подібного виду дозволу імені до Haskell, але він пропонує використовувати локальні обмеження, щоб відстежувати, підтримує якийсь тип певну операцію чи ні. Тож у першому зразку вимога, яка xпотребує Valueвластивості, переноситиметься до тих пір, поки xsне буде видно, і ця вимога може бути вирішена. Це, однак, ускладнює систему типів.
Більше спекуляцій, цього разу з боку переважно Хаскелл ...
($)це фліп (|>), і його використання є досить поширеним, коли ви не можете написати безточний код. Отже, головна причина, що (|>)не використовується в Haskell, полягає в тому, що її місце вже зайнято ($).
Крім того, кажучи з трохи досвіду F #, я думаю (|>), що такий популярний у F # коді, оскільки він нагадує Subject.Verb(Object)структуру ОО. Оскільки F # має на меті плавну функціональну / інтеграцію OO, Subject |> Verb Objectце досить плавний перехід для нових функціональних програмістів.
Особисто мені теж подобається думати зліва направо, тому я використовую (|>)в Haskell, але я не думаю, що так багато інших людей.
Data.Sequence.|>, але $>здається розумним уникати конфліктів там. Чесно кажучи, є лише стільки гарних операторів, тому я просто використовую |>для обох і керую конфлікти в кожному конкретному випадку. (Крім того, я був би спокуса просто псевдонім , Data.Sequence.|>як snoc)
($)і (|>)є застосуванням не складом. Два пов'язані (як питання примітки) , але вони не збігаються (ваше fcє (Control.Arrow.>>>)для функцій).
|>насправді більше нагадує мені UNIX, |ніж будь-що інше.
|>F # є те, що він має приємні властивості для IntelliSense у Visual Studio. Введіть |>і ви отримаєте список функцій, які можна застосувати до значення зліва, подібного до того, що відбувається під час введення тексту .після об’єкта.
Я думаю, що ми плутаємо речі. Haskell's ( .) еквівалентний F # 's ( >>). Не плутати з F # 's ( |>), який є просто перевернутим додатком функції і схожий на 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
$оператор - звернуто, ви можете легко визначити його як: a |> b = flip ($)яке стає еквівалентно F # 's трубопроводу , наприклад , ви можете зробити[1..10] |> map f
.) те саме, що ( <<), тоді як ( >>) - зворотний склад. Це ( >> ) : ('T1 -> 'T2) -> ('T2 -> 'T3) -> 'T1 -> 'T3проти( << ) : ('T2 -> 'T3) -> ('T1 -> 'T2) -> 'T1 -> 'T3
.це рівнозначно >>. Я не знаю, чи є F #, <<але це було б еквівалентом (як у Elm).
Якщо ви хочете використовувати F # 's |>в Haskell, то в Data.Function є &оператором (з тих пір base 4.8.0.0).
&більш |>? Я відчуваю, що |>набагато інтуїтивніше, і це також нагадує мені оператора труб Unix.
Деякі користуються стилем зліва направо (передача повідомлень) і в 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]
Існує вагома причина, щоб іноді віддавати перевагу композиції зліва направо: оцінка порядку дотримується порядку читання.
Я бачив, як >>>його використовують flip (.), і я часто це використовую сам, особливо для довгих ланцюгів, які найкраще розуміють зліва направо.
>>> насправді від Control.Arrow і працює над більш ніж просто функціями.
>>>визначено в Control.Category.
Окрім стилю та культури, це зводиться до оптимізації мовного дизайну для чистого чи нечистого коду.
|>Оператор часто зустрічається в F # в основному тому , що це допомагає приховати два обмеження , які з'являються з переважно-нечистим кодом:
Зауважимо, що колишнє обмеження не існує в OCaml, оскільки підтипізація є структурною замість номінальної, тому структурний тип легко уточнюється за допомогою уніфікації в міру просування виводу типу.
Haskell робить інший компроміс, вирішивши зосередитись на переважно чистому коді, де ці обмеження можна зняти.
Я думаю, що оператор F #'s pipe forward ( |>) повинен проти ( & ) у 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 Functionабо closure 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/
Він підтримує:
Це мій перший день спробувати Haskell (після Rust і F #), і я зміг визначити оператора F # '|>:
(|>) :: a -> (a -> b) -> b
(|>) x f = f x
infixl 0 |>
і, здається, працює:
factorial x =
case x of
1 -> 1
_ -> x * factorial (x-1)
main =
5 |> factorial |> print
Надіюсь, що експерт Haskell може дати вам ще краще рішення.
x |> f = f x
&це Хаскелл|>. Заглибився глибоко в цю нитку і знадобився мені кілька днів, щоб відкрити. Я його дуже використовую, тому що ви, природно, читаєте зліва направо, щоб слідувати коду.