2016-05-18 23 views
7

Wiem, że w Haskell, jest niesamowite funkcja o nazwie funkcja skład tak, że możemy uczynić nasz kod Haskell pithier, jak:Jak używać funkcji składu dla `foo (bar x) (bar y)` w Haskell?

  • użytku (f . g) x zamiast f (g x),
  • użycie foo x $ bar y z zamiast foo x (bar y z)

Ale czy jest możliwe, że moglibyśmy użyć składu funkcji dla foo (bar x) (bar y)?

+1

zauważyć, że w przyszłości, można spróbować użyć [Hoogle] (https://www.haskell.org/hoogle/?hoogle= (b% 20-% 3E% 20b% 20 -% 3E% 20c)% 20-% 3E% 20 (a% 20-% 3E% 20b)% 20-% 3E% 20a% 20-% 3E% 20a% 20-% 3E% 20c) w celu wyszukania funkcji chcesz, co w rzeczywistości daje użyteczną odpowiedź tutaj. :) –

Odpowiedz

13

Można użyć funkcji on za to, na przykład

import Data.Function 

data Person = Person{name::String, age::Int} 

compare `on` age --same as `\x y -> compare (age x) (age y)` 
+0

Choć dobrze jest wiedzieć, mam wrażenie, że "duch" pytania był znacznie szerszy niż to. Pierwotne pytanie dotyczyło - jeśli możesz - "radości i wygody kompozycji". W mojej wyobraźni byłoby to pytanie równoważne, gdyby żądanie dotyczyło ** foo (bar x) (bar y) (bar z) **. To znaczy, nie sądzę, że było to pytanie o "arial 2". Jako że twoja odpowiedź jest rzeczowa, wstrzymałem się od głosu ... ale ... jest dla mnie rozczarowaniem (w moim dążeniu do nauki samego Haskella), że jest to uważane za doskonałą odpowiedź na pytanie. – HostileFork

+0

@HostileFork W pytaniu użyto zarówno "(.)", Jak i '($)" jako przykładów "kompozycji", więc wydaje mi się całkiem prawdopodobne, że pytanie to zadano z bardziej ogólnym zrozumieniem "kompozycji" na uwadze, że prosty operator składu funkcji. Haskell ma wiele narzędzi w swoim zestawie narzędzi do łączenia funkcji, a możliwość znalezienia odpowiedniego do danej pracy jest często ważniejsza niż użycie najbardziej ogólnego wzoru. To powiedziawszy, twoja interpretacja pytania wydaje się interesująca i nie miałbym nic przeciwko próbie odpowiedzi na to pytanie, jeśli opublikujesz je osobno, z nieco większą szczegółowością. –

+1

@AlexisKing * "więc wydaje mi się całkiem prawdopodobne, że pytanie to zostało zadane z bardziej ogólnym zrozumieniem" kompozycji "w umyśle" * - Być może po prostu widząc to przez oczy uczącego się języka, twierdzę, że jest odwrotnie - że wskazuje na brak zrozumienia rozróżnienia tego, czym jest skład matematyczny. Naprawdę zgaduję, że moja skarga dotyczy tylko tego, że jest to bardzo trudny język do nauczenia się i nie wydaje mi się, że stanie się łatwiejsze, jeśli zapytasz o coś takiego i nakręcisz "curry (uncurry f. (G *** g))" jako odpowiedź, wyjaśnienie sans. Wygląda na to, że ludzie nie "słyszeli tego, o co pytano". – HostileFork

4

zdefiniować go samemu! Tylko nowa funkcja infix:

-- foo (bar x) (bar y) === foo $.$ bar (x y) 
($.$) :: (b -> b -> c) -> (a -> b) -> (a -> a -> c) 
f $.$ g = \x y -> f (g x) (g y) 

-- test 3 5 = 3*3 + 5*5 
test = (\x y -> x + y) $.$ (\z -> z * z) 

Następnie w ghci:

ghci> test 3 5 
34 
2

to możliwe, że mogliśmy korzystać złożenie funkcji dla foo (bar x) (bar y)

@ilyavf dał odpowiedź, dla definicji funkcji takiej, że (foo $.$ bar) x y będzie działał jak foo (bar x) (bar y). I @jamshidh oferuje, że istnieje jako on w Data.Function.

jednak zauważyć podpis typu o to rodzaj specyficznego kształtu:

(b -> b -> c) -> (a -> b) -> (a -> a -> c) 

Jako funkcja, choć to „kształt zabawny” ze względu na założeniu, że ma do wykonania. To założenie jest takie, że oba argumenty foo są tego samego typu. (inaczej, jak może być poprawne użycie wyniku dla obu?)

"Bardziej przyjemny kształt", do którego grawituje Haskell, nie przywołuje szczególnego przypadku pracy z funkcjami, które mają dwa argumenty tego samego typu. Bo co jest takiego specjalnego w 2? O wiele bardziej interesujące jest "N", a jeśli twoja funkcja przyjmuje N argumentów tego samego typu, to lista jest ładniejsza ... i może komponować, jak chcesz, z operacją mapy, która może działać z dowolną liczbą argumentów:

foo [bar x, bar y] =>(foo . map bar) [x, y]

+1

To nie zadziała, jeśli 'bar' to, powiedzmy,' show'. –

+3

@TaylorFausak Właśnie się uczę * (i próbuję zacząć uczyć się przez odpowiedź) *, więc będziesz musiał mi wytłumaczyć, co masz na myśli. Ponieważ próbuję takich rzeczy jak 'concat [pokaż 10, pokaż 20] =>" 1020 "', a następnie '(zobacz mapę pokaż) [10, 20] =>" 1020 "' i zakończ, że musi działać. Ale jestem gotów się mylić, gdziekolwiek coś Haskelly'ego dotyczy. – HostileFork

+0

Powiedziałbym, że lista jest zbyt szczegółowa. Jeśli twoja funkcja przyjmuje dokładnie dwa (lub trzy, lub cztery) argumenty, to użycie pośredniej listy spowoduje stronniczość wtrysku. Zamiast tego możesz użyć dowolnego 'Funktora', który pozwoli na listy, niestandardowe typy krotek, listy indeksowane długością (to jest zależne wektory) itd. – dfeuer

2

Control.Arrow alternatywa:

curry (uncurry f . (g *** g)) 

Nie tak czytelne jak poprzednio opublikowanych rozwiązań.

+1

'na gf = (.f). g. f' – user3237465

+0

Dlaczego zrobiłbyś coś tak okropnego? Ewww! – dfeuer

+0

@dfeuer Nie chciałbym w prawdziwym kodzie, nie martw się. ;-) – chi

2

Pointless odpowiedniki dla \x y -> foo (bar x) (bar y):

+0

To interesujące (i jeszcze inna odmienna interpretacja intencji OP z pytaniem ... które może być właściwe, chociaż sugerowałoby, że ramka powinna być ** foo (bar x) (baz y) **) – HostileFork

Powiązane problemy