2013-07-31 12 views
7

Powiedzmy mam listę funkcjiFunkcja w Haskell

functions = [f, g, h] 

każdy z rodzaju a -> a

Mam też listę wartości, powiedzmy numery ale coś powinno działać tutaj

vals = [1,2,3] 

Chcę zastosować każdą funkcję w functions do odpowiedniej wartości w vals

Moim pierwszym odruchem jest użycie lambda i zipWith jak:

zipWith (\f v -> f v) functions vals 

Ale szczerze to wygląda brzydko, a nie coś, czego można oczekiwać w takim ładnym językiem jak Haskell. Funkcja aplikacji funkcji brzmi jak rozwiązanie. Czy jest coś takiego? Czy brakuje mi czegoś i jest o wiele ładniejsze rozwiązanie mojego problemu? Skończyło się na napisaniu tego konstruktu dla rozwiązania Project Euler. Działa, ale nie podoba mi się to.

Odpowiedz

16
zipWith ($) f v 

$ to aplikacja funkcji. Fakt, że ma wyjątkowo niski priorytet, czasami rzuca ludzi w pętlę.

11

dziwo

zipWith id functions vals 

zadziała też!

Ale naprawdę, zipWith ($) to właściwy sposób na napisanie tego.

+0

Każdy pomysł, dlaczego to działa? –

+14

@JuanPablo Ponieważ '$' jest tak naprawdę tylko 'id', specjalizuje się tylko w pracy nad funkcjami (i ma bardzo niski priorytet oraz notację infiksową). Typ '$', ponieważ stosuje funkcję do argumentu, musi być '(a -> b) -> a -> b'. Pamiętając, że wszystkie funkcje Haskella są "naprawdę" unarne (lub równoważne, że '->" kojarzy się z prawą), ten sam typ co '(a -> b) -> (a -> b)'. Co oznacza, że ​​przyjmuje funkcję dowolnego typu i daje funkcję tego samego typu; tylko specjalny przypadek 'id :: a -> a', który przyjmuje wartość dowolnego typu i daje wartość tego samego typu. – Ben

+6

Inny sposób na to: użycie 'zipWith id' oznacza, że ​​każdy wynikowy element jest obliczany przez' id f v', a 'id f' jest równy' f', więc 'id f v' równy' f v'. – augustss

3

Oto kolejna opcja, która może trochę myśleć.

>>> import Control.Applicative 
>>> let functions = ZipList [(+1), (*2), (*10)] 
>>> let values = ZipList [1, 2, 3] 
>>> getZipList (functions <*> values) 
[2, 4, 30] 

A ZipList to tylko opakowanie na liście. Definicja <*> dla ZipList mówi "zip listę funkcji (po lewej) z listą argumentów (po prawej) przez zastosowanie każdej funkcji do argumentu po kolei".

Jest to sprzeczne z definicją <*> dla zwykłej listy, która mówi "weź każdą możliwą parę (funkcję, argument) z tych dwóch list i zastosuj funkcję do argumentu".