2014-07-15 16 views
5

Aktualnie przesyłam kod z tradycyjnego Scala do stylu Scalaz.Scalaz Bind [Seq] typeclass

To dość powszechne, ponieważ większość mojego kodu używa bezpośrednio cechy Seq w moich odsłoniętych sygnaturach API, a nie konkretnym typie (np. Lista, Wektor). Jednak powoduje to pewien problem ze Scalazem, ponieważ nie zapewnia implementacji typu typowego Bind [Seq].

tj. To zadziała poprawnie.

List(1,2,3,4) >>= bindOperation 

Ale to nie

Seq(1,2,3,4) >>= bindOperation 

będzie niepowodzeniem z błędem could not find implicit value for parameter F0: scalaz.Bind[Seq]

Zakładam, że jest to zamierzona decyzja projektowa w Scalaz - jednak jestem pewien, przeznaczonej/najlepszych praktyk na temat poprzedzać .

Czy zamiast tego powinienem napisać mój kod bezpośrednio do Listy/Wektorów zamiast używać bardziej elastycznego interfejsu Seq? Czy powinienem po prostu zdefiniować własną czcionkę Bind [Seq]?

+1

Istnieje jednak monadowa instancja 'IndexedSeq'. – rightfold

Odpowiedz

11

Biblioteka kolekcji wykonuje backflipy w celu dostosowania podtytułów: przy korzystaniu z dla określonego typu kolekcji (lista, mapa itp.), (Zazwyczaj) odzyskujesz ten sam typ. Zarządza nim poprzez użycie klasy an extremely complex inheritance hierarchy wraz z klasami typów, takimi jak CanBuildFrom. Wykonuje to zadanie (przynajmniej można to przypuszczać), ale złożoność nie jest bardzo pryncypialna. To bałagan. Wiele osób go nienawidzi.

Złożoność jest na ogół dość łatwa do uniknięcia jako użytkownik biblioteki, ale dla projektanta bibliotecznego to koszmar. Jeśli dostarczę instancję monady dla Seq, oznacza to, że wszystkie typy moich użytkowników są podnoszone w hierarchii do Seq każdego typu, w którym używają monadycznej operacji.

Scalaz ludzie zwykle nie lubią Subtyping bardzo dużo, tak, więc w przeważającej części Scalaz pozostaje wokół liści hierarchy- List, Vector, itd. Można zobaczyć dyskusję o tej decyzji on the mailing list, na przykład.

Kiedy po raz pierwszy zacząłem używać Scalaz napisałem dużo kodu użytkowego, który próbował dostarczyć instancji dla Seq itp. I uczynić je użytecznymi z CanBuildFrom. Potem zatrzymałem się i teraz mam tendencję do podążania za Scalazem tylko w moim własnym kodzie, używając tylko List, Vector, Map i Set. Jeśli jesteś zaangażowany w styl "Scalaz", powinieneś to również zrobić (lub nawet przyjąć własny Scalaz, IList, ISet, ==>> itd.). Nie znajdziesz jednak jasnego porozumienia w sprawie najlepszych praktyk, a oba podejścia mogą sprawnie działać, więc po prostu musisz poeksperymentować, aby znaleźć to, co lubisz.

+1

Jest to również powodem, na przykład 'scalaz.NonEmptyList [T]' nie jest podtypem 'Seq [T]'? – rightfold

+1

@rightfold: Tak, i nie byłbym zbyt zaskoczony, gdyby 'NonEmptyList' stał się pewnego dnia niezmienny, co jest kolejnym powodem, aby nie utknąć w bagnie' Seq'. –