2013-04-24 17 views
7

Próbuję przerobić wszystkie moje problemy domowe Haskell za pomocą Erlang, a jedną rzeczą, która mnie do mnie, jest to, jak korzystać z listy funkcji, które nie mają wszystkich swoich parametrów.Funkcje Curling Erlang

Przykład: Staram się używać tego krotnie, ale nie wiem jak przekazać w funkcji tak, że działa na akumulatorze

%%inside my module) 
add(X,Y) -> X + Y. 

multiply(X,Y) -> X*Y. 

Następnie przy użyciu tego w wierszu poleceń:

lists:foldl(fun(Function,Accumulator) -> Function(Accumulator) end, 3, [add(3),multiply(5)]). 

Odpowiedz

9

W Erlang trzeba przechodzącą wszystkie parametry funkcji wymaga to nazwać. Można go jednak łatwo ominąć, tworząc anonimową funkcję, która pobiera tylko te parametry, które są potrzebne, a następnie prawidłowo wywołuje funkcję. Jeśli potrzebujesz funkcję, która przyjmuje jeden parametr X i wywołuje funkcję Add (3 X) można utworzyć anonimową funkcję tak:

fun (X) -> add(3, X) end 

To jest przykład dla zadania:

lists:foldl(fun (Function, Accumulator) -> Function(Accumulator) end, 3, 
    [fun (X) -> add(3, X) end, fun (X) -> multiply(5, X) end]). 
0
lists:foldl(
    fun(Function,Accumulator) -> Function(Accumulator) end, 
    3, 
    [ 
     fun(X) -> modname:add(3, X) end, 
     fun(X) -> modname:multiply(5, X) end 
    ] 
). 
+0

Oznacza to, że w Erlang nie ma funkcji częściowej funkcji (i bez curry), prawda? Ponieważ używasz funkcji lambda, podczas gdy w Haskell możemy mieć listę częściowych funkcji (?): '[(+) 1, (-) 2, (*) 3]'. Czy jest to wciąż to samo, co zastosowanie częściowej funkcji? – ichistmeinname

1

Można dość łatwo napisać częściową funkcję aplikacji, która nazywa się analogicznie do erlang: apply/3. Brakuje mu elegancji w językach, które wspierają curry.

-module(partial). 

-export([apply/4]). 

apply(Module, Name, Arity, Args) when length(Args) < Arity -> 
    Left = Arity - length(Args), 
    fun(Args1) when length(Args1) < Left -> 
      fun(Args2) -> 
       apply(Module, Name, Arity, Args2 ++ Args1 ++ Args) 
      end; 
     (Args1) when length(Args1) > Left -> 
      erlang:error(badarg); 
     (Args1) -> 
      erlang:apply(Module, Name, Args1 ++ Args) 
    end; 
apply(_, _, Arity, Args) when length(Args) > Arity -> 
    erlang:error(badarg); 
apply(Module, Name, _, Args) -> 
    erlang:apply(Module, Name, Args). 
3

Pod względem rodzimych Erlang nie ma żadnej formy częściowej oceny, jak chcesz. Będziesz musiał stworzyć własną zabawę, aby to zrobić. Jeśli jednak używasz Erlando Monad Library, możesz użyć dopasowania do wzoru, aby go utworzyć. Działa dzięki temu, że kompilator erlang pozwala grać z AST przy kompilowaniu kodu, dzięki czemu możesz robić fajne rzeczy w ten sposób.