2010-09-24 18 views
13

Czy istnieje elegancka notatka na temat Sprzeczanie argumentów funkcji nieczynnej w Haskell?Wykonywanie polecenia w Haskell

Na przykład, jeśli chcesz podzielić 2 przez wszystkich elementów listy, można napisać

map ((/) 2) [1,2,3,4,5] 

jednak podzielić wszystkie elementy listy wydaje trzeba zdefiniować anonimową funkcję

map (\x -> x/2) [1,2,3,4,5] 

Anonimowe funkcje szybko stają się nieporęczne w bardziej złożonych przypadkach. Mam świadomość, że w tym przypadku mapa ((*) 0.5) [1,2,3,4,5] działałaby dobrze, ale chciałbym wiedzieć, czy Haskell ma bardziej elegancki sposób na wygłaszanie argumentów funkcji nieczynny?

+0

'flip' i backticks są dobre wraz z prostym użyciem funkcji infix (jak zauważa delnan). –

Odpowiedz

16

W tym konkretnym przypadku:

Prelude> map (/2) [1..5] 
[0.5,1.0,1.5,2.0,2.5] 

Nie tylko można użyć odpowiedniego operatora Infix jako zwyczajne funkcji prefiksu, można również częściowo stosuje się go w postaci Infix. Podobnie, pierwszy przykład lepiej być zapisany jako map (2/) [1..5]

Ponadto, jest tam flip który nie jest tak elegancki, ale nadal najlepsza opcja dostępna dla zwykłych funkcji (jeśli nie chcesz, aby przekształcić je w wrostkiem poprzez backticks) :

Prelude> let div' = (/) 
Prelude> div' 2 1 
2.0 
Prelude> flip div' 2 1 
0.5 
+0

Czy działa to tylko z operatorami? A co z dowolnymi funkcjami? – Gabe

+0

@Gabe: jak napisał FUZxxl, działa również z funkcjami, które są używane infix (otaczając je backticks). Podam przykład, ale już go dostarczył. – delnan

+0

Dziękuję.Szkoda, że ​​nie ma takiej składni jak f 1 2 # 4 #, która ma taki sam efekt jak \ x y -> f 1 2 x 4 y. – hosiers

2

na swoim drugim, lambda jest niepotrzebny, wystarczy użyć jak:

map (/2) [1..5] 

postaci (/ 2) oznacza po prostu, że chcesz uzyskać dostęp do drugiego param operatora. Jest również możliwe z pierwszym argumentem (2/). Nazywa się to sekcja i jest naprawdę przydatnym hackerem, nie tylko w kodzie golfowym. Można również użyć go w funkcji przedrostek, jeśli ich używać Infix:

map (`div` 2) [1..5] 

W trudniejszych przypadkach, jak 3 lub więcej argumentów, jesteś powinien używać lambdy, jak staje się bardziej czytelne najwięcej razy.

2

Myślę, że szukasz uogólnionego rozwiązania, takiego jak cut w schemacie. Dobrze?

Istnieje funkcja flip, która odwraca pierwsze 2 argumenty funkcji. Mogą być inne funkcje wykonujące podobne zadanie (nie jestem zbyt dobry w Haskell ... jeszcze).

+1

'flip' nie odwraca listy argumentów. Po prostu odwraca pierwsze dwa, rozważ to: 'flip (.) :: (a -> b) -> (b -> c) -> a -> c'. -1 – fuz

0

natknąłem się very similar issue się niedawno i nie był w stanie znaleźć eleganckie rozwiązanie inne niż przy użyciu funkcji pomocnika to zrobić:

dbfunc f b c = (\a -> liftIO $ f a b c) 
deleteAllRows = do 
    ask >>= dbfunc run "delete from t1" [] 

Przynajmniej ten wzór jest dosyć powszechne w HDBC tym dbfunc jest wielokrotnego użytku.

+0

'ask >> = liftIO. (przerzucenie.) "usuń z t1" []) ' – is7s

+0

Dla pewnych wartości elegancji ;-) – Gaius

Powiązane problemy