Kolejność parametrów w celu wykorzystania curry

93

Niedawno dwukrotnie refaktoryzowałem kod, aby zmienić kolejność parametrów, ponieważ było zbyt dużo kodu, w którym hacki takie jak fliplub \x -> foo bar x 42miały miejsce.

Jakie zasady pomogą mi jak najlepiej wykorzystać curry podczas projektowania podpisu funkcji?

John F. Miller
źródło

Odpowiedzi:

111

W przypadku języków, które obsługują curry i łatwe częściowe stosowanie, istnieje jedna przekonująca seria argumentów, oryginalnie od Chrisa Okasakiego:

  • Jako ostatni argument umieść strukturę danych

Czemu? Następnie możesz ładnie komponować operacje na danych . Np insert 1 $ insert 2 $ insert 3 $ s. Pomaga to również w funkcjach na stanie .

Standardowe biblioteki, takie jak „kontenery”, są zgodne z tą konwencją .

Czasami podaje się alternatywne argumenty, aby umieścić strukturę danych jako pierwszą, więc można ją zamknąć, uzyskując funkcje na strukturze statycznej (np. Wyszukiwanie), które są nieco bardziej zwięzłe. Wydaje się jednak, że istnieje powszechna zgoda co do tego, że jest to mniej korzystne, zwłaszcza że popycha cię do kodu umieszczonego w nawiasach.

  • Najbardziej zróżnicowany argument umieść na końcu

W przypadku funkcji rekurencyjnych często umieszcza się argument, który zmienia się najbardziej (np. Akumulator) jako ostatni argument, podczas gdy argument, który zmienia się najmniej (np. Argument funkcji) na początku. To dobrze komponuje się z ostatnim stylem struktury danych.


Podsumowanie widoku Okasaki znajduje się w jego bibliotece Edisona (znowu, w innej bibliotece struktur danych):

  • Częściowe zastosowanie : argumenty z większym prawdopodobieństwem są statyczne zwykle pojawiają się przed innymi argumentami w celu ułatwienia częściowego zastosowania.
  • Kolekcja pojawia się jako ostatnia : we wszystkich przypadkach, gdy operacja wysyła zapytanie do pojedynczej kolekcji lub modyfikuje istniejącą kolekcję, argument kolekcji pojawi się jako ostatni. Jest to coś w rodzaju faktycznego standardu dla bibliotek datastruktur Haskell i nadaje pewną spójność API.
  • Najbardziej typowa kolejność : gdy operacja reprezentuje dobrze znaną funkcję matematyczną na więcej niż jednej strukturze danych, argumenty są wybierane tak, aby pasowały do ​​najczęściej stosowanej kolejności argumentów funkcji.
Don Stewart
źródło
W następstwie pierwszego wypunktowania argument, który może występować w strukturze danych, należy umieścić na końcu. Sprawia, że ​​mapa, składanie i przyjaciele są czystsze. tl; dr rzecz na liście przejdź jako ostatnia.
John F. Miller
1
Lookup i tak nie może być powiązany, więc pierwszy punkt tego nie obsługuje. haskell.org/haskellwiki/Parameter_order tworzy przekonywujący argument na odwrót - „Ponieważ obiekty typu Map reprezentują odwzorowania, naturalne jest posiadanie funkcji, która przekształca obiekt Map w reprezentowaną funkcję”.
Brandon,
11

Najpierw umieść argumenty, których najprawdopodobniej użyjesz ponownie. Argumenty funkcji są tego doskonałym przykładem. Bardziej prawdopodobne jest map f, że będziesz chciał mieć więcej niż dwie różne listy, niż mapować wiele różnych funkcji na tej samej liście.

hammar
źródło
5
Jeśli faktycznie mapujesz wiele funkcji na tej samej liście, być może powinieneś zrobić listę funkcji, a map ($myList)zamiast tego na tej liście.
Squidly
3

Zwykle robię to, co zrobiłeś, wybieram jakieś zamówienie, które wydaje się dobre, a następnie refaktoryzuję, jeśli okaże się, że inne zamówienie jest lepsze. Kolejność zależy w dużej mierze od tego, jak zamierzasz używać funkcji (naturalnie).

augustss
źródło